瀏覽器中的 CSS 支持指南
已發表: 2022-03-10我們永遠不會生活在一個每個瀏覽我們網站的人都擁有相同瀏覽器和瀏覽器版本的世界中,就像我們永遠不會生活在一個每個人都擁有相同大小的屏幕和分辨率的世界中一樣。 這意味著處理舊瀏覽器——或者不支持我們想要使用的東西的瀏覽器——是 Web 開發人員工作的一部分。 也就是說,現在的情況比過去好得多,在本文中,我將看看我們可能遇到的不同類型的瀏覽器支持問題。 我將向您展示一些處理它們的方法,並查看可能即將推出的可以提供幫助的東西。
為什麼我們有這些差異?
即使在大多數瀏覽器都基於 Chromium 的世界中,這些瀏覽器也並非都運行與 Google Chrome 相同版本的 Chromium。 這意味著基於 Chromium 的瀏覽器(例如 Vivaldi)可能比 Google Chrome 落後幾個版本。
而且,當然,用戶並不總是快速更新他們的瀏覽器,儘管近年來這種情況有所改善,大多數瀏覽器都在默默地升級自己。
還有新功能首先進入瀏覽器的方式。 CSS 的新特性並不是由 CSS 工作組設計的,而是將完整的規範傳遞給瀏覽器供應商,並附有實現它的說明。 很多時候,只有當一個實驗性的實現發生時,規範的所有更精細的細節才能被制定出來。 因此,功能開發是一個迭代過程,需要瀏覽器在開發中實現這些規範。 雖然這些天來實現通常發生在瀏覽器中的標誌後面或僅在夜間或預覽版本中可用,但一旦瀏覽器具有完整的功能,即使沒有其他瀏覽器支持,它也可能會為每個人打開它。
所有這一切意味著——儘管我們可能喜歡它——我們將永遠不會存在於一個功能可以神奇地同時在每個桌面和手機上可用的世界。 如果您是專業的 Web 開發人員,那麼您的工作就是處理這個事實。
錯誤與缺乏支持
我們在瀏覽器支持方面面臨三個問題:
- 不支持某個功能
第一個問題(也是最容易處理的)是瀏覽器根本不支持該功能。 - 處理瀏覽器“錯誤”
第二種是瀏覽器聲稱支持該功能,但這樣做的方式與其他瀏覽器支持該功能的方式不同。 這樣的問題我們傾向於稱為“瀏覽器錯誤”,因為最終結果是不一致的行為。 - 部分支持 CSS 屬性
這個變得越來越普遍; 瀏覽器支持某項功能的情況——但僅限於一個上下文。
當您看到瀏覽器之間的差異時,了解您正在處理的問題會很有幫助,因此讓我們依次看看這些問題中的每一個。
1. 不支持某個功能
如果您使用瀏覽器不理解的 CSS 屬性或值,瀏覽器將忽略它。 無論您使用不受支持的功能,還是編造一個功能並嘗試使用它,這都是一樣的。 如果瀏覽器不理解那行 CSS,它會跳過它並繼續它理解的下一個內容。
CSS 的這種設計原則意味著您可以愉快地使用新功能,因為沒有支持的瀏覽器不會發生任何不好的事情。 對於某些純粹用作增強的 CSS,這就是您需要做的所有事情。 使用該功能,確保當該功能不可用時,體驗仍然很好,僅此而已。 這種方法是漸進增強背後的基本思想,使用平台的這一特性可以在不理解它們的瀏覽器中安全地使用新事物。
如果您想檢查瀏覽器是否支持您正在使用的功能,那麼您可以查看 Can I Use 網站。 尋找細粒度支持信息的另一個好地方是 MDN 上每個 CSS 屬性的頁面。 那裡的瀏覽器支持數據往往非常詳細。
新 CSS 理解舊 CSS
隨著新 CSS 功能的開發,需要注意它們與現有 CSS 的交互方式。 例如,在 Grid 和 Flexbox 規範中,詳細說明了display: grid
和display: flex
如何處理浮動項變為網格項,或多列容器變為網格等場景。 這意味著某些行為被忽略,幫助您簡單地覆蓋不支持瀏覽器的 CSS。 這些覆蓋在 MDN 上的漸進增強和網格佈局頁面中有詳細說明。
使用功能查詢檢測支持
上述方法僅在您需要使用的 CSS 不需要其他屬性的情況下才有效。 您可能需要為舊瀏覽器的 CSS 添加其他屬性,然後這些屬性也將由支持該功能的瀏覽器進行解釋。
使用網格佈局時可以找到一個很好的例子。 雖然成為網格項的浮動項會失去所有浮動行為,但如果您嘗試為具有浮動的網格佈局創建後備,您可能會為項目添加百分比寬度和可能的邊距。
.grid > .item { width: 23%; margin: 0 1%; }
當浮動項目是網格項目時,這些寬度和邊距仍然適用。 寬度變成網格軌道的百分比而不是容器的全寬; 然後將應用任何保證金以及您可能指定的差距。
.grid > .item { width: 23%; margin: 0 1%; } .grid { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; column-gap: 1%; }
值得慶幸的是,有一個內置在 CSS 中並在現代瀏覽器中實現的功能,可以幫助我們處理這種情況。 功能查詢允許我們直接詢問瀏覽器它們支持什麼,然後根據響應採取行動。 就像媒體查詢(測試設備或屏幕的某些屬性)一樣,功能查詢測試是否支持 CSS 屬性和值。
測試支持
測試支持是最簡單的情況,我們使用@supports
然後測試 CSS 屬性和值。 Feature Query 中的內容只有在瀏覽器響應 true 時才會運行,即它確實支持該功能。
測試不支持
您可以詢問瀏覽器是否不支持某個功能。 在這種情況下,功能查詢中的代碼只有在瀏覽器指示它不支持時才會運行。
@supports not (display: grid) { .item { /* CSS from browsers which do not support grid layout */ } }
測試多種事物
如果您需要支持多個屬性,請使用and
。
@supports (display: grid) and (shape-outside: circle()){ .item { /* CSS from browsers which support grid and CSS shapes */ } }
如果您需要一個或另一個屬性的支持,請使用or
。
@supports (display: grid) or (display: flex){ .item { /* CSS from browsers which support grid or flexbox */ } }
選擇要測試的屬性和值
您不需要測試您想要使用的每個屬性 - 只需表明對您計劃使用的功能的支持。 因此,如果你想使用網格佈局,你可以測試display: grid
。 將來(一旦瀏覽器支持子網格),您可能需要更具體並測試子網格功能。 在這種情況下,您將測試grid-template-columns: subgrid
以僅從那些實現了 subgrid 支持的瀏覽器中獲得真正的響應。
如果我們現在回到我們的浮動後備示例,我們可以看到特徵查詢將如何為我們排序。 我們需要做的是查詢瀏覽器,看看它是否支持網格佈局。 如果是這樣,我們可以將項目的寬度設置回auto
並將邊距設置為0
。
.grid > .item { width: 23%; margin: 0 1%; } @supports(display: grid) { .grid { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; column-gap: 1%; } .grid > .item { width: auto; margin: 0; } }
請注意,雖然我在功能查詢中包含了所有網格代碼,但我不需要。 如果瀏覽器不理解網格屬性,它將忽略它們,因此它們可以安全地位於特徵查詢之外。 在這個例子中,必須在特徵查詢中的東西是邊距和寬度屬性,因為這些是舊瀏覽器代碼所需要的,但也會被支持的瀏覽器應用。
擁抱瀑布
提供回退的一個非常簡單的方法是利用瀏覽器忽略他們不理解的 CSS 的事實,以及在其他所有內容具有相同特異性的情況下,根據 CSS 應用於元素的方式考慮源順序.
您首先為不支持該功能的瀏覽器編寫 CSS。 然後測試您想要使用的屬性的支持,如果瀏覽器確認它支持用您的新代碼覆蓋回退代碼。
這與您在使用媒體查詢進行響應式設計時可能使用的過程幾乎相同,遵循移動優先的方法。 在這種方法中,您從較小屏幕的佈局開始,然後在您向上移動通過斷點時為較大的屏幕添加或覆蓋內容。
上述工作方式意味著您無需擔心不支持功能查詢的瀏覽器。 從Can I Use可以看出,Feature Queries 有非常好的支持。 不支持它們的傑出瀏覽器是任何版本的 Internet Explorer。
但是,您要使用的新功能很可能在 IE 中也不受支持。 因此,目前您幾乎總是從為不支持的瀏覽器編寫 CSS 開始,然後使用 Feature Query 進行測試。 此功能查詢應測試支持。
- 支持功能查詢的瀏覽器將在支持時返回 true,因此將使用查詢中的代碼,覆蓋舊瀏覽器的代碼。
- 如果瀏覽器支持功能查詢但不支持正在測試的功能,它將返回 false。 功能查詢中的代碼將被忽略。
- 如果瀏覽器不支持功能查詢,那麼功能查詢塊內的所有內容都將被忽略,這意味著 IE11 等瀏覽器將使用您的舊瀏覽器代碼,這很可能正是您想要的!
2. 處理瀏覽器“Bug”
幸運的是,第二個瀏覽器支持問題變得不那麼常見了。 如果您閱讀了“我們希望什麼”(去年年底出版),您可以了解過去一些更令人費解的瀏覽器錯誤。 也就是說,任何軟件都有可能出現錯誤,瀏覽器也不例外。 而且,如果我們再加上一個事實,由於規範實現的循環性質,有時瀏覽器實現了一些東西,然後規範發生了變化,所以他們現在需要發布更新。 在該更新發布之前,我們可能處於瀏覽器執行不同操作的情況。
如果瀏覽器報告對某些東西的支持很糟糕,功能查詢就無法幫助我們。 沒有一種模式可以讓瀏覽器說:“是的,但你可能不會喜歡它。” 當出現實際的互操作性錯誤時,正是在這些情況下,您可能需要更有創意。
如果您認為您看到了一個錯誤,那麼首先要做的是確認這一點。 有時,當我們認為我們看到了錯誤的行為,並且瀏覽器在做不同的事情時,問題就在我們身上。 也許我們使用了一些無效的語法,或者正在嘗試設置格式錯誤的 HTML。 在這些情況下,瀏覽器會嘗試做一些事情; 但是,由於您沒有使用它們設計的語言,因此每個瀏覽器可能以不同的方式應對。 快速檢查您的 HTML 和 CSS 是否有效是很好的第一步。
那時,我可能會快速搜索一下,看看我的問題是否已經被廣泛理解。 有一些已知問題的存儲庫,例如 Flexbugs 和 Gridbugs。 但是,即使是精心挑選的幾個關鍵字,也可以出現涵蓋該主題的 Stack Overflow 帖子或文章,並可能為您提供解決方法。
但是,假設您真的不知道是什麼導致了這個錯誤,這使得尋找解決方案變得非常困難。 因此,下一步是為您的問題創建一個簡化的測試用例,即剔除任何不相關的內容,以幫助您準確識別觸發錯誤的原因。 如果你認為你有一個 CSS 錯誤,你可以刪除任何 JavaScript,或者在框架之外重新創建相同的樣式嗎? 我經常使用 CodePen 將我看到的東西的簡化測試用例放在一起; 這還有一個額外的好處,就是以一種我可以在需要詢問時輕鬆與其他人分享的方式給我代碼。
大多數情況下,一旦您隔離了問題,就有可能想出另一種方法來實現您想要的結果。 你會發現其他人想出了一個巧妙的解決方法,或者你可以在某個地方發帖尋求建議。
話雖如此,如果您認為您有瀏覽器錯誤並且找不到其他人談論相同的問題,那麼您很可能發現了應該報告的新內容。 隨著最近出現的所有新 CSS,當人們開始將事物與 CSS 的其他部分結合使用時,有時會出現問題。
查看 Lea Verou 關於報告此類問題的帖子,“幫助社區! 報告瀏覽器錯誤!”。 這篇文章還提供了創建簡化測試用例的重要技巧。
3. CSS屬性的部分支持
由於現代 CSS 規範的設計方式,第三類問題變得更加普遍。 如果我們考慮 Grid Layout 和 Flexbox,這些規範都使用 Box Alignment Level 3 中的屬性和值來進行對齊。 因此,諸如align-items
、 justify-content
和column-gap
等屬性被指定用於 Grid 和 Flexbox 以及其他佈局方法。
然而,在撰寫本文時, gap
屬性在所有支持網格的瀏覽器中都適用於 Grid Layout,而column-gap
則適用於 Multicol; 但是,只有 Firefox 為 Flexbox 實現了這些屬性。
如果我要使用邊距為 Flexbox 創建後備,然後測試column-gap
並刪除邊距,我的盒子在支持 Grid 或 multicol 中的column-gap
的瀏覽器中將沒有空間,所以我的後備間距將是刪除。
@supports(column-gap: 20px) { .flex { margin: 0; /* almost everything supports column-gap so this will always remove the margins, even if we do not have gap support in flexbox. */ } }
這是功能查詢的當前限制。 我們沒有辦法測試另一個功能是否支持某個功能。 在上述情況下,我想問瀏覽器的是,“Flexbox 中是否支持 column-gap?” 這樣,我可以得到一個否定的回應,所以我可以使用我的後備。
CSS 碎片屬性break-before
、 break-after
和break-inside
也有類似的問題。 由於這些在打印頁面時具有更好的支持,因此瀏覽器通常會聲稱支持。 但是,如果您在 multicol 中測試支持,您會得到看似誤報的結果。 我已經在 CSS 工作組就這個問題提出了一個問題,但是,這不是一個簡單的問題要解決。 如果您有想法,請在此處添加。
測試選擇器支持
目前,功能查詢只能測試 CSS 屬性和值。 我們可能想要測試的另一件事是對較新選擇器的支持,例如選擇器規範第 4 級中的選擇器。 在 Firefox Nightly 中,有一個解釋說明和一個標誌背後的一個實現,它是功能查詢的新功能,它將實現這一點。
如果您在 Firefox 中訪問about:config
並啟用標誌layout.css.supports-selector.enabled
那麼您可以測試是否支持各種選擇器。 語法目前非常簡單,例如測試:has
選擇器:
@supports selector(:has){ .item { /* CSS for support of :has */ } }
這是一個正在開發的規範,但是,您可以看到在我們發言時如何添加幫助我們管理瀏覽器支持問題的功能。
延伸閱讀
當您想使用一項功能並發現一個主要瀏覽器不支持它,或者事情似乎以不同的方式表現時,這似乎令人沮喪。 我收集了一些可能有幫助的實用進一步閱讀。
- “使用 CSS Grid: Supporting Browsers without Grid”處理舊瀏覽器和 CSS Grid 的選項
- 功能查詢的“功能查詢”MDN 參考頁面
- “CSS 網格和漸進增強” MDN 網格漸進增強指南
- “Flexbox 的向後兼容性” MDN 對 Flexbox 支持的指南,包括舊前綴實現的詳細信息
- “模式庫優先”如何使用模式庫管理回退代碼