CSS層疊技術(shù):優(yōu)化CSS重置,打造獨(dú)特樣式
這篇文章介紹了一種名為CSS層疊的技術(shù),用于優(yōu)化CSS重置過程。它解釋了CSS重置的概念,即通過刪除瀏覽器默認(rèn)樣式來確保在不同瀏覽器上呈現(xiàn)一致的外觀。然后,它引入了CSS層疊技術(shù),以更好地控制樣式的層次結(jié)構(gòu)和優(yōu)先級(jí)。
文章詳細(xì)討論了CSS層疊技術(shù)的使用方法和優(yōu)勢(shì)。它介紹了幾個(gè)關(guān)鍵概念,包括層疊順序、z軸定位和層疊上下文等。它還提供了實(shí)際的示例和代碼片段,以幫助讀者理解如何使用CSS層疊來實(shí)現(xiàn)更好的樣式控制和管理。
該文章還提到了使用CSS層疊技術(shù)時(shí)可能遇到的一些挑戰(zhàn)和注意事項(xiàng)。它建議在使用CSS層疊時(shí)要小心處理層疊順序和優(yōu)先級(jí),以避免樣式?jīng)_突和不一致的呈現(xiàn)。
下面是正文~~
我一直是傾向于使用更為積極的CSS重置方法的人。這些方法會(huì)清除瀏覽器中大部分默認(rèn)的樣式,例如,它會(huì)移除從<h1>到<h6>元素默認(rèn)的標(biāo)題樣式,這些樣式通常具有較大的字體大小和字體粗細(xì)。
然而,我也喜歡 Normalize CSS 如何處理陰影 DOM 元素,這是我們?cè)谌魏?CSS 重置方法中都沒有的。
然而,我也喜歡Normalize CSS處理影子DOM元素的方式,這是我們?cè)谌魏蜟SS重置方法中都沒有的。 因此,我總是在尋找方法將它們兩者結(jié)合起來。即便如此,我仍然遇到了一些CSS優(yōu)先級(jí)問題,需要找到一種解決方法。
快進(jìn)到今天,所有的瀏覽器現(xiàn)在都支持CSS層。因此,在開發(fā)Appwrite的開源設(shè)計(jì)系統(tǒng)Pink Design時(shí),我們開始重新思考如何更好地處理這個(gè)問題。
在我們開始之前,讓我們先談?wù)勔恍╆P(guān)于CSS重置方法的內(nèi)容。
CSS重置方法
多年來,一直存在著一種“爭(zhēng)論”,即哪種CSS重置方法更好。
在這次比賽中,我們采用了兩種熟悉的方法:
- **Normalize CSS ** — 一種溫和的方法,可以修復(fù)瀏覽器之間的差異,同時(shí)保留HTML元素的本地樣式,例如 <h1> , <h2> 等標(biāo)題元素。
如之前提到的,Normalize CSS也負(fù)責(zé)處理在不同瀏覽器中可能會(huì)有差異展現(xiàn)的Shadow DOM元素。
Normalize CSS 中處理 Shadow DOM 元素的演示:
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
- CSS Reset —— 相較而言,CSS重置是一種更為激進(jìn)的方法,常常會(huì)廢除瀏覽器“用戶代理樣式表”的默認(rèn)樣式。
CSS重置演示:
此代碼將撤銷 <h1> 的特殊 font-size 、 font-weight 和 margin ,將其轉(zhuǎn)換為 <h6> 元素:
h1, h2, h3, h4, h5, h6 {
margin: 0;
font-size: inherit;
font-weight: inherit;
}
方法的結(jié)合
通過結(jié)合 Normalize CSS 和 CSS Reset 兩種方法,你可以從兩種方法中獲益。
這樣可以確保處理內(nèi)部 shadow DOM元素,并忽略從“用戶代理樣式表”繼承的無用樣式。實(shí)現(xiàn)這一點(diǎn)最簡(jiǎn)單的方法是同時(shí)加載兩者。以下是如何在Sass預(yù)處理器中實(shí)現(xiàn)的演示:
/* CSS Resets */
@use 'normalize';
@use 'reset';
你可能會(huì)認(rèn)為,如果我們首先加載Normalize CSS,然后再加載CSS Reset,這會(huì)使我們的CSS Reset具有更強(qiáng)的特異性,對(duì)嗎?不完全是這樣的;讓我們談?wù)勥@方面的一些問題。
合并方法的問題
在Appwrite Pink中,我們使用Normalize CSS,同時(shí)與“新的CSS重置方法”結(jié)合使用?!靶碌腃SS重置方法”是一種新的重置CSS的方式,利用了新的原生CSS重置功能。
對(duì)于“Normalize CSS”和“The New CSS Reset”這兩個(gè)項(xiàng)目,我們都是原封不動(dòng)地使用它們(來自NPM),甚至包括來自Normalize CSS的不必要部分,比如修復(fù)<h1>元素的不同樣式,這將會(huì)在CSS重置中被移除。
“Normalize CSS”中的 Header <h1> 樣式:
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
在“The New CSS Reset”中,通用移除樣式(包括元素):
/*
Remove all the styles of the "User-Agent-Stylesheet",
except for the 'display' property.
- The "symbol *" part is to solve Firefox SVG sprite bug
*/
*:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) {
all: unset;
display: revert;
}
但是這里開始出現(xiàn)了問題。為了理解這些問題,讓我們先談?wù)劵镜腃SS,它定義了我們的樣式:
順序很重要
CSS選擇器的順序很重要。這是因?yàn)橥ǔG闆r下,后面的樣式比前面的樣式更強(qiáng)。在我們的情況下,CSS重置文件的順序是正確的。
首先,我們想要加載“Normalize CSS”,它將規(guī)范化不同瀏覽器之間的差異,然后我們想要使用CSS重置來刪除我們不需要的內(nèi)容,在我們的情況下,這是使用“The New CSS Reset”完成的。
Scss 導(dǎo)入的示例:
/* CSS Resets files order */
@use 'normalize'; /* 1 */
@use 'reset'; /* 2 */
/* In general, last code is stronger in CSS */
CSS 優(yōu)先級(jí)
我們根據(jù)CSS選擇器的強(qiáng)度(元素、類名和ID名)來定義我們選擇器的優(yōu)先級(jí)。從最弱到最強(qiáng)的選擇器依次為元素選擇器、類選擇器和ID選擇器。
在這個(gè)例子中,ID選擇器將贏得“CSS特異性戰(zhàn)爭(zhēng)”,因?yàn)镮D選擇器比類名選擇器或元素選擇器更強(qiáng)。
這意味著 <h1> 元素的顏色將會(huì)是粉色。
<h1 class="title" id="mainTitle">some content</h1>
#mainTitle { color:pink; } /* 1 (ID), 0 (Classes), 0(element) */
.title { color:yellow; } /* 0 (ID), 1 (Classes), 0(element) */
h1 { color:red; } /* 0 (ID), 0 (Classes), 1(element) */
我們的CSS特異性沖突
如果我們看一下<h1> 元素的Normalize CSS選擇器,它具有一個(gè)元素的能力:
/* 0 (ID), 0 (Classes), 1 (element) */
h1 {...}
這是一個(gè)相對(duì)較低強(qiáng)度的選擇器。
讓我們來看一下來自“The New CSS Reset”的主要CSS重置選擇器:
/* 0 (ID), 0 (Classes), 0 (element) */
*:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) {...}
為了盡可能地降低特異性,使用 :where() 偽選擇器。 :where() 偽選擇器的主要思想之一是消除選擇器創(chuàng)建的任何CSS特異性。
但這里產(chǎn)生了沖突,<h1>的樣式比CSS重置的樣式更為強(qiáng)大,這對(duì)我們來說是個(gè)問題。
解決這個(gè)沖突的一種方法是移除 Normalize CSS 中不必要的部分,也就是移除所有非 Shadow DOM 部分的樣式。但是,如果我們從 NPM 包中自動(dòng)加載項(xiàng)目,這可能會(huì)成為一個(gè)問題,因?yàn)檫@樣很難維護(hù)。
CSS Layers 來拯救
CSS層是為了解決這樣的問題而發(fā)明的,即我們希望告訴瀏覽器,特定的層比其他層更重要,并忽略其他層的CSS優(yōu)先級(jí)。
為了做到這一點(diǎn),我們有@layer規(guī)則,這規(guī)則定義了一個(gè)層。它將部分樣式包裹起來,定義層的部分,并在層自身內(nèi)部實(shí)行CSS優(yōu)先級(jí)。
這個(gè)做法本身就能解決我們的問題。
為了更精確地定義層的順序,我們可以添加一個(gè) @layer,這將決定你希望代碼按何種順序出現(xiàn)。
@layer normalize {
/* CSS Normalize Here */
}
@layer the-new-css-reset {
/* CSS Reset here */
}
這本身就會(huì)解決我們的問題。為了更精確地定義層的順序,我們可以添加“l(fā)ayer statement”,以確定你希望代碼出現(xiàn)的順序。
示例:
/* layer statement - define the order,
even if the order of the code will not be in the same way */
@layer normalize, the-new-css-reset;
@layer normalize {
/* CSS Normalize Here */
}
@layer the-new-css-reset {
/* CSS Reset here */
}
Sass 預(yù)處理器支持
@use 'sass:meta';
@layer normalize, the-new-css-reset;
@layer normalize {
@include meta.load-css('normalize');
}
@layer the-new-css-reset {
@include meta.load-css('the-new-css-reset');
}
這樣,我們可以將CSS層分別保存在不同的文件中,并確保在保持代碼整潔的同時(shí),最后一層能在“樣式優(yōu)先級(jí)之爭(zhēng)”中勝出。
瀏覽器支持
CSS layers 已經(jīng)在所有主流瀏覽器中實(shí)現(xiàn)了相當(dāng)長的時(shí)間
圖片
總結(jié)
本文主要探討了我們?nèi)绾谓鉀QCSS優(yōu)先級(jí)問題,尤其是關(guān)于CSS重置層面的問題。
隨著我們接近2023年底,隨著用戶升級(jí)他們的瀏覽器,這種使用CSS層來解決CSS沖突的方法將越來越常見。
在構(gòu)建Pink Design的過程中,我們有幸為開發(fā)者這種類型的用戶提供服務(wù),他們通常會(huì)定期更新瀏覽器。因此,我們選擇了采用這種新的、利用CSS層進(jìn)行開發(fā)的方法。