在 CSS 裏,有一個你可能沒有聽過的工具,可是它已經出現一段時間了,並且很是強大。也許,它會成爲 CSS 中你最喜歡的東西之一。css
那麼,是什麼呢?就是 @support
,也就是功能查詢。web
經過 @support
,你能夠在 CSS 中使用一小段的測試來查看瀏覽器是否支持一個特定的 CSS 功能(這個功能能夠是 CSS 的某種屬性或者某個屬性的某個值),而後,根據測試的結果來決定是否要應用某段樣式。好比:npm
@supports ( display: grid ) { // 若是瀏覽器支持 Grid,這裏面的代碼纔會執行 }
若是瀏覽器可以理解 display: grid
,那麼,大括號裏的代碼都會被應用,不然,這些樣式就會被跳過。gulp
如今,對於功能查詢是什麼,你也許還有一點疑惑。這並非經過某種額外的驗證來分析瀏覽器是否已經確切的實現了某個 CSS 屬性。若是你須要查看額外的驗證,能夠查看 Test the Web Forward。瀏覽器
功能查詢讓瀏覽器本身就可以表現出是否支持某個 CSS 屬性或者 CSS 屬性值。而後經過這個結果來判斷是否要應用某段 CSS。若是一個瀏覽器沒有正確的(或者徹底的)實現一個 CSS 屬性,那麼,@supports
就沒有什麼用了。它並非一個可以讓瀏覽器的 bug 消失的魔杖。ide
可是,我已經發現 @supports
是那麼難以置信的有幫助。比起之前沒有這個屬性的時候,@supports
可以讓我一再的使用新的 CSS 功能。grunt
多年以來,開發者們都在使用 Modernizr 來實現功能查詢,可是 Modernizr 須要 JavaScript。雖然這部分 JavaScript 很小,可是,CSS 結構中添加了 Modernizr 的話,在 CSS 被應用以前,就須要下載 JavaScript 而後等待執行完成。比起使用 CSS,加入了 JavaScript 老是會更慢。並且,要是 JavaScript 執行失敗了呢?另外,Modernizr 還須要一層額外複雜的、不少項目都沒法理解的東西。相比之下,功能查詢更快,功能更強大,使用起來更簡單。工具
你也許注意到了,@supports
的寫法和媒體查詢很相似,我以爲他們可能就是堂兄弟的關係。佈局
@supports ( display: grid ) { main { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); } }
大多數時候,你其實不須要這樣的測試。好比,你能夠直接這樣寫:測試
aside { border: 1px solid black; border-radius: 1em; }
若是瀏覽器可以理解 border-radius
,那麼,在相應的容器上就會應用圓角樣式。若是它不能理解這個屬性,那麼,就會直接跳過並繼續執行下面的語句。容器的邊緣也就保持直角了。徹底沒有必要使用功能查詢或者測試,CSS 就是這樣運做的。這是屬於 CSS 中穩固設計,漸進加強的一個基本的原則。瀏覽器會直接跳過他們沒法解析的語句,不會拋出任何錯誤。
大多數瀏覽器都會應用
border-radius: 1em;
,而後展現出右邊的效果。可是,在 IE6,7,8 上你卻不能看到圓角,你看到的將是左邊的效果。能夠看看這個例子:A Rounded Corner Box。
對於這個例子,沒有必需要使用功能查詢。
那麼,何時才須要使用 @supports
呢?功能查詢是將 CSS 聲明綁定在一塊兒的一個工具,以便於這些 CSS 規則可以在某種條件下以一個組合的方式運行。當你須要混合使用 CSS 的新規則和舊規則的時候,而且,僅當 CSS 新功能被支持的時候,就可使用功能查詢了。
譯者注:如下例子中的
initial-letter
屬性如今在全部現代瀏覽器中都不受支持,因此,如下例子中的代碼可能都是無效的代碼。若是下文中有提到此屬性在某某瀏覽器中受支持的話,請忽略。須要瞭解initial-letter
詳細的說明,能夠參考 initial-letter | MDN。
來看一個關於使用 initial-letter
的例子。這個屬性告訴瀏覽器要將特指的那個元素變得更大,就像一個段首大字同樣。在這裏,咱們要作的就是讓段落的第一個字母的大小爲四行文字那麼大。同時,咱們再對它進行加粗,在它的右邊設置一些 margin,還給它設置一個高亮的橘色。OK,很不錯了。
p::first-letter { margin-right: 0.5em; color: #FE742F; font-weight: bold; -webkit-initial-letter: 4; initial-letter: 4; }
這是在 Safari 上的效果
讓咱們看看在其餘瀏覽器上的效果。
好吧,簡直無法接受。除了使用 initial-letter
來達到咱們想要的效果以外,咱們並不想要改變字體的 color
,margin
,和 font-weight
。因此,咱們須要一個方法來測試瀏覽器是否支持 initial-letter
這個屬性,而後在瀏覽器支持這個屬性的時候再應用相關的樣式。因此,使用功能查詢:
@supports (initial-letter: 4) or (-webkit-initial-letter: 4) { p::first-letter { -webkit-initial-letter: 4; initial-letter: 4; color: #FE742F; font-weight: bold; margin-right: 0.5em; } }
注意,測試的時候須要進行徹底的測試,CSS 屬性和值都得寫上。一開始我也比較疑惑,爲何非得測試 initial-letter: 4
呢?4
這個值很重要嗎?若是我寫成 17
呢?莫非是須要匹配我即將要應用的 CSS 中的樣式嗎?
緣由是這樣的:@supports
在測試的時候,須要提供屬性和值,由於有時候測試的是屬性,有時候測試的是值。對於 initial-letter
,你輸入多少值並不重要。可是,若是是 @suports ( dislay: grid )
就不同了,全部瀏覽器都識別 display
,可是,並非全部瀏覽器都識別 display: grid
。
回到咱們的例子,當前的 initial-letter
只在 Safari 9 上受支持,而且須要加前綴。因此,我加了前綴,同時,保持着不加前綴的規則,而且,我還寫了測試來測試另外的屬性。沒錯,在功能查詢中,還可使用 and, or, not
聲明。
下面是新的結果。理解 initial-letter
的瀏覽器會顯示一個巨大加粗高亮的段首大字。其餘瀏覽器的行爲就像是這個段首大字不存在同樣。固然,若是更多的瀏覽器支持了這個屬性,那麼,他們的行爲也將會是有一個段首大字。
如今,也許你火燒眉毛的想要使用這個工具來將你的代碼分爲兩個分支,使其變得乾淨一些。「Hey,瀏覽器,若是你識別 Viewport 單位,就執行這個,不然,執行另外的」。感受很不錯,有條理。
@supports ( height: 100vh ) { // 支持 viewport height 的樣式 } @supports not ( height: 100vh ) { // 對於舊瀏覽器的替代樣式 } // 咱們但願是好的,但這是一段爛代碼
這段代碼並很差,至少當前看來是這樣的。發現問題了嗎?
問題就是,並非全部的瀏覽器都支持功能查詢,不理解 @supports
的瀏覽器會直接跳過兩段代碼,這也許就太糟糕了。
意思就是,除非瀏覽器百分之百支持功能查詢,不然咱們就無法使用了嗎?固然不是,咱們徹底可使用功能查詢,並且應該使用功能查詢,只要不像上面那樣寫代碼就行。
那麼,怎麼作纔對呢?其實與使用媒體查詢相似,咱們在瀏覽器徹底支持媒體查詢以前就開始使用了不是嗎?事實上,功能查詢使用起來比媒體查詢更簡單,只要腦子放聰明一點就好了。
你想要讓你的代碼知道瀏覽器是否支持功能查詢或者正在測試的某個功能,我來告訴你怎麼作。
固然,在將來,瀏覽器 100% 支持功能查詢的時候,咱們能夠大量使用
@supports not
來組織咱們的代碼。
因此,@supports
如今支持度什麼樣了呢?
自從 2013 年中,@supports
就可以在 Firefox,Chrome 和 Opera 中使用了。在 Edge 的各個版本中也受支持。Safari 在 2015 年秋季才實現這個功能。具體的支持狀況,請看下面這張圖:
你可能會以爲 IE 不支持此功能會是一個大問題,可是,其實不是這樣的。待會兒就會告訴你緣由。我相信,最大的一個障礙是 Safari 8,咱們須要留意在這個瀏覽器上發生的事情。
讓咱們來看另一個例子。假設咱們有些佈局代碼,爲了正常運行,須要使用 object-fit: cover;
。對於不支持這個屬性的瀏覽器,咱們想要使用不一樣的樣式。
因此,咱們能夠這樣寫:
@supports (initial-letter: 4) or (-webkit-initial-letter: 4) { p::first-letter { -webkit-initial-letter: 4; initial-letter: 4; color: #FE742F; font-weight: bold; margin-right: 0.5em; } } div { width: 300px; background: yellow; } @supports (object-fit: cover) { img { object-fit: cover; } div { width: auto; background: green; } }
會發生什麼呢?@supports
有支持或者不支持的狀況,object-fit
也有支持或者不支持的狀況,因此,就有了四種可能性:
功能查詢支持狀況 | 屬性(或者值)支持狀況 | 會發生什麼 | 是否咱們想要的 |
---|---|---|---|
支持 | 不支持 | CSS 將會被應用 | 是 |
支持 | 不支持 | CSS 不會被應用 | 是 |
不支持 | 支持 | CSS 不會被應用 | 是 |
不支持 | 不支持 | CSS 不會被應用 | 否 |
因此,咱們應該怎麼寫功能查詢的代碼呢?像下面這樣:
// fallback code for older browsers @supports ( display: grid ) { // code for newer browsers // including overrides of the code above, if needed }
譯者注:本文的主要內容是介紹功能查詢和
@supports
的使用方法,因此,某些代碼多是沒法運行的,但願讀者們注意。同時,因爲原文中的一些內容顯得比較冗餘,因此部份內容並無翻譯。若是須要了解詳細內容,請查看原文。
翻譯自 Using Feature Queries in CSS