關鍵要點
選擇器特異性對於大多數中大型項目來說都是一個真正的問題,與任何其他經常重複出現的編碼問題一樣,它需要仔細處理。甚至 CSS-Tricks 最近也有一篇文章介紹如何保持 CSS 特異性較低。在你嘗試使用 !important
之前,讓我提醒你:> CSS/日常技巧:如果所有內容都是 !important
,則沒有任何內容是 !important
。 ——Tony Nelson (@tonynelson19) 2010 年 11 月 18 日
CSS 特異性並不復雜,但社區已經做了很多工作來使其盡可能易於理解,通過使用與魚和星球大戰的類比或使用撲克術語來編寫指南。在線有交互式計算器可用,甚至還有 Sass 的特異性 mixin,允許你檢查並輸出選擇器的精確特異性值。在 CSS 特異性策略中,越簡單越好,本文中的特異性解決方法(可能感覺有點笨拙)適用於架構不允許簡單修復的情況。在決定哪種方法最適合你的項目時,請運用你的判斷力,並最終嘗試在乾淨且易於維護的 CSS 之間取得完美的平衡。
方法 0 – BEM
BEM 不僅僅是一種命名約定,它是由 Yandex 發明的前端工具包,其理念是更接近面向對象編程。在實踐中,這意味著為你要設置樣式的每一件事都使用類名。雖然“在層疊樣式表中不進行層疊”對某些人來說可能聽起來很荒謬,但在創建應該易於維護、可移植、自給自足、易於修改和可擴展的模塊時,避免使用類型選擇器和避免嵌套的想法非常有幫助。然而,BEM 方法的主要優點之一是它使每個選擇器的特異性保持不變,因此幾乎不會出現由過於具體的選擇器引起的問題,這就是為什麼這種方法是0 號方法——如果你採用它,你實際上消除了項目中選擇器特異性方面未來出現的任何問題。
由於你將只為編寫的所有內容使用單個類,因此每個選擇器的特異性都將為 0,1,0
有無數關於使用 BEM 的前端架構的成功案例,然而,儘管 BEM 非常流行,但它並不適用於特定類型的項目。它似乎非常適合前端開發人員是唯一編寫 HTML 的項目。但是,如果你為內容編輯器至少編寫部分內容的 CMS 編寫內容,則 BEM 將受到嚴重限制。 BEM 的純形式不允許嵌套和類型選擇器,例如 .Section--dark > a
(例如,使其具有淺色),而是要求你為錨點標籤發明一個類。這導致了一個問題——內容編輯器將通過圖形界面插入默認鏈接,這可能會導致鏈接幾乎不可見。這也可能適用於特定部分中的所有段落、列表或圖像。有時需要能夠編寫不帶類的純 HTML 內容,在這種情況下,解決方案是讓父級使用後代選擇器對其進行樣式設置。這種級聯的使用允許上下文靈活性——當某些內容位於不同的上下文中時,它會具有自定義樣式。因此,我們需要一個實際的解決方案,用於我們無法使用純 BEM 的情況,這種情況相當常見。 CSS 預處理器可以在這裡幫助我們,所有 3 個流行的預處理器——LESS、Sass 和 Stylus 都能夠在我們需要使用更具體的選擇器覆蓋選擇器時簡化我們的工作。
方法 1 – 使用選擇器添加前綴
當你遇到特異性問題並想要使某個選擇器更重時,你可以在現有選擇器前添加類、屬性、ID 或類型選擇器。通過這種方式,你可以稍微提高特異性。雖然此功能主要用於使用條件 html 標籤定位 IE,但它還有更多有待開發的功能。 CSS 預處理器中的父引用選擇器 (&) 可以輕鬆地讓我們添加選擇器前綴以使其更重,因此我們可以執行以下操作:
<code>.class { body & { foo: bar; } }</code>
生成的 CSS:
<code>.class { body & { foo: bar; } }</code>
你可能希望使用 html 或 body 標籤添加前綴,但你也可以使用頁面上存在的一些更具體的內容,例如 .page
、#wrapper
、html[lang]
等。 Sass 允許你在將來發生更改時將添加前綴的選擇器放在變量中,此外,對於大型項目,可能值得創建一組具有不同權重的添加前綴的選擇器:
<code>body .class { foo: bar; }</code>
這將生成:
<code>$prepend1: "html &"; $prepend2: "#wrapper &"; .selector { #{$prepend1} { background: #cacaca; } #{$prepend2} { background: #fefefe; } }</code>
其他流行的預處理器,如 LESS 和 Stylus 也提供此功能。
使用類型選擇器為我們最初的類選擇器 0,1,0 添加前綴將導致 0,1,1,使用 ID 添加前綴 – 1,1,0。這裡的缺點是,一旦你使用代碼中最重的選擇器(即#wrapper
)添加了某個選擇器的前綴,你就無法再覆蓋它,除非你發明一個新的、更重的選擇器,而這並非總是可能的。
方法 2 – 自鏈選擇器
添加選擇器前綴很有用,但它不是無限可擴展的解決方案——你可能只有有限的方法來定位父級。此外,一旦你使用代碼中最重的選項為多個選擇器添加了前綴,你就會限制以後解決特異性問題的選項(特別是如果你使用了 ID)。前端社區最近被提醒了一個非常有用的 CSS 功能——自鏈選擇器來提高其特異性。自鏈選擇器適用於 ID、類和屬性選擇器,但不適用於類型選擇器。但是,如果你主要使用類來設置內容樣式,則自鏈選擇器為你提供了一種無限可擴展的方式來覆蓋任何選擇器。借助父引用選擇器,你可以輕鬆地將相同的選擇器多次鏈接到自身(這適用於 ID、類和屬性選擇器,但不適用於類型選擇器)。但是,你需要在第一個之後插入每個 &,最低要求是 Sass 3.4:
<code>html .selector { background: #cacaca; } #wrapper .selector { background: #fefefe; }</code>
<code>.selector { {&} { background: #cacaca; } {&}{&} { background: #fefefe; } }</code>
同樣,你也可以使用 LESS 和 Stylus 執行此操作。如果這對你的口味來說太難看,你可以隨時創建一個 mixin,它可以迭代地提高任何單個選擇器的特異性。此 mixin 使用一些高級功能,也需要 Sass 3.4:
<code>.selector.selector { background: #cacaca; } .selector.selector.selector { background: #fefefe; }</code>
生成的 CSS:
<code>@mixin specificity($num: 1) { $selector: &; @if $num > 1 { @for $i from 1 to $num { $selector: $selector + &; } @at-root #{$selector} { @content; } } @else { @content; } } .selector { @include specificity(2) { background: #cacaca; } @include specificity(3) { background: #fefefe; } }</code>
你可以在 Stylus 中創建相同的 mixin,不幸的是,在 LESS 中沒有簡單的方法可以創建這樣的 mixin。
自鏈將選擇器的特異性從 0,1,0 提高到 0,2,0,再到 0,3,0,依此類推,使其幾乎無限可擴展。
最終想法
在我們比以往任何時候都更智能的CSS 中處理特異性問題的下一個自然步驟是創建一種方法來識別衝突的聲明,使用David Khourshid 的Sass mixin 之類的東西計算每個實體的特異性,然後自動使用上述方法之一來提高特異性。也許我對自我感知樣式表的夢想過於樂觀,但我認為隨著 CSS 預處理器的發展,我們代碼中復雜的邏輯將會增加。下次你需要處理特異性問題時,你會使用上述哪種方法?你使用什麼其他策略來解決你的特異性問題?
關於 CSS 預處理器和選擇器特異性的常見問題
選擇器特異性是 CSS 中的一個概念,它確定在存在衝突規則時將哪些樣式應用於元素。它是一個分配給不同類型選擇器(例如 ID、類和類型選擇器)的權重系統。在 Sass 或 Less 等 CSS 預處理器中,此概念保持不變。但是,這些預處理器提供了額外的功能,例如嵌套,這會影響選擇器的特異性。
嵌套是 CSS 預處理器中的一項功能,允許你編寫更有條理且更易於閱讀的代碼。但是,它也會增加選擇器的特異性。每個嵌套級別都會增加特異性,使嵌套選擇器比父選擇器更具體。這對於覆蓋樣式很有用,但如果管理不當,也可能導致意想不到的後果。
選擇器的特異性是根據使用的選擇器類型計算的。通常,ID 選擇器的特異性最高,其次是類選擇器,然後是類型選擇器。每種類型的選擇器都分配不同的權重,總特異性是這些權重的總和。一些 CSS 預處理器,如 Sass,提供用於計算選擇器特異性的函數。
“&”符號用於 Sass 等 CSS 預處理器中,以引用嵌套規則中的父選擇器。這對於創建更具體的選擇器或將樣式應用於元素的不同狀態(如懸停或活動狀態)很有用。
在 Sass 中,你可以通過複製選擇器來提高其特異性。這被稱為鏈接或雙選擇器。例如,.class.class
的特異性將高於 .class
。但是,應謹慎使用此方法,因為它會使你的 CSS 更難維護和覆蓋。
高特異性會使你的 CSS 更難維護和覆蓋。它可能導致所謂的特異性衝突,你必須不斷提高選擇器的特異性才能覆蓋之前的樣式。這會導致 CSS 膨脹和復雜。
有幾種策略可以管理 CSS 預處理器中的特異性。一種是盡可能使用低特異性選擇器。另一種是避免不必要的嵌套,因為這會增加特異性。你還可以使用 BEM(塊、元素、修飾符)方法來保持特異性較低且一致。
是的,你可以使用 !important
規則來覆蓋 CSS 預處理器中的特異性。但是,這應該作為最後手段,因為它會使你的 CSS 更難維護,並可能導致特異性衝突。
選擇器的順序會影響 CSS 預處理器中的特異性。如果兩個選擇器的特異性相同,則 CSS 中最後出現的選擇器將被應用。這稱為源順序特異性。
是的,內聯樣式在 CSS 中具有最高的特異性,可以覆蓋其他樣式。但是,應謹慎使用它們,因為它們會使你的 CSS 更難維護,並可能導致樣式不一致。
以上是CSS預處理器的選擇器特異性的詳細內容。更多資訊請關注PHP中文網其他相關文章!