處理常見的 HTML 和 CSS 問題
場景設定完畢,我們現在將具體探討在 HTML 和 CSS 程式碼中常見的跨瀏覽器問題,以及可以使用哪些工具來防止問題發生或修復已出現的問題。這包括程式碼 Lint、處理 CSS 字首、使用瀏覽器開發工具追蹤問題、使用 Polyfill 為瀏覽器新增支援、解決響應式設計問題等等。
| 預備知識 | 熟悉核心的 HTML、CSS 和 JavaScript 語言;瞭解 跨瀏覽器測試的高階原則。 |
|---|---|
| 目標 | 能夠診斷常見的 HTML 和 CSS 跨瀏覽器問題,並使用適當的工具和技術來修復它們。 |
HTML 和 CSS 的麻煩
HTML 和 CSS 的部分麻煩在於這兩種語言都相當簡單,開發者通常不會認真對待它們,例如確保程式碼結構良好、高效,並語義化地描述頁面上功能的目的。在最糟糕的情況下,JavaScript 被用來生成整個網頁內容和樣式,這使得你的頁面無法訪問,並且效能較差(生成 DOM 元素成本很高)。在其他情況下,新興功能在瀏覽器之間支援不一致,這可能導致某些功能和樣式對某些使用者不起作用。響應式設計問題也很常見——一個在桌面瀏覽器中看起來不錯的網站,在移動裝置上可能會提供糟糕的體驗,因為內容太小無法閱讀,或者網站由於昂貴的動畫而速度緩慢。
讓我們繼續看看如何減少由 HTML/CSS 導致的跨瀏覽器錯誤。
首先:解決一般問題
我們在本系列的第一篇文章中提到,一個好的開始策略是在桌面/移動裝置上的幾個現代瀏覽器中進行測試,以確保你的程式碼正常工作,然後再專注於跨瀏覽器問題。
在我們的 除錯 HTML 和 除錯 CSS 文章中,我們提供了一些關於除錯 HTML/CSS 的非常基本的指導——如果你不熟悉這些基礎知識,你 definitely 應該在繼續閱讀之前學習這些文章。
基本上,就是檢查你的 HTML 和 CSS 程式碼是否格式良好,不包含任何語法錯誤。
注意:CSS 和 HTML 的一個常見問題是不同的 CSS 規則開始相互衝突。當使用第三方程式碼時,這尤其成問題。例如,你可能會使用一個 CSS 框架,並發現它使用的某個類名與你已經用於不同目的的類名發生衝突。或者你可能會發現由某種第三方 API(例如生成廣告橫幅)生成的 HTML 包含你已經用於不同目的的類名或 ID。為確保這種情況不會發生,你需要首先研究你正在使用的工具,並圍繞它們設計你的程式碼。對 CSS 進行“名稱空間”也值得,例如,如果你有一個小部件,請確保它有一個獨特的類,然後用這個類開始選擇小部件內部元素的選擇器,這樣衝突的可能性就會降低。例如 .audio-player ul a。
驗證
對於 HTML,驗證涉及確保所有標籤都正確關閉和巢狀,你正在使用 doctype,並且你正在為正確的目的使用標籤。一個好的策略是定期驗證你的程式碼。可以做到這一點的一項服務是 W3C Markup Validation Service,它允許你指向你的程式碼,並返回錯誤列表。

CSS 也有類似的情況——你需要檢查屬性名稱是否拼寫正確,屬性值是否拼寫正確並且對其使用的屬性有效,是否沒有遺漏任何花括號等等。W3C 也有一個 CSS Validator 可供此目的使用。
Linters
另一個不錯的選擇是所謂的 Linter 應用程式,它不僅指出錯誤,還可以標記 CSS 中不良實踐的警告以及其他一些點。Linter 通常可以自定義,使其在錯誤/警告報告方面更嚴格或更寬鬆。
有許多線上 Linter 應用程式,例如用於 HTML、CSS 和 JavaScript 的 Dirty Markup。這些應用程式允許你將程式碼貼上到視窗中,它會用叉號標記任何錯誤,然後可以懸停叉號以獲取告知你問題是什麼的錯誤訊息。Dirty Markup 還允許你使用清除按鈕修復你的標記。

然而,多次將程式碼複製貼上到網頁上以檢查其有效性並不方便。你真正想要的是一個能夠以最小的麻煩融入你的標準工作流程的 Linter。
許多程式碼編輯器都有 Linter 外掛。例如,請參見
- Sublime Text 的 SublimeLinter
- Notepad++ linter
- VS Code linters
瀏覽器開發者工具
大多數瀏覽器內建的開發者工具也具有用於查詢錯誤的有用工具,主要用於 CSS。
注意:HTML 錯誤在開發者工具中不容易顯示,因為瀏覽器會嘗試自動更正格式錯誤的標記;W3C 驗證器是查詢 HTML 錯誤的最佳方法——參見上文 驗證。
例如,在 Firefox 中,CSS 檢查器將顯示未應用的 CSS 宣告,並帶有警告三角形。將滑鼠懸停在警告三角形上將提供描述性錯誤訊息。

其他瀏覽器開發者工具也有類似的功能。
常見的跨瀏覽器問題
現在讓我們繼續討論一些最常見的跨瀏覽器 HTML 和 CSS 問題。我們將主要關注缺乏對現代功能的支援以及佈局問題。
瀏覽器不支援現代功能
這是一個常見問題,尤其是在你需要支援舊瀏覽器或者你使用的功能在某些瀏覽器中實現但尚未在所有瀏覽器中實現時。通常,大多數核心 HTML 和 CSS 功能(例如基本的 HTML 元素、CSS 基本顏色和文字樣式)在你想要支援的所有瀏覽器中都能正常工作;當你開始使用較新的 HTML、CSS 和 API 時,會發現更多問題。MDN 為每個文件化的功能顯示瀏覽器相容性資料;例如,請參閱 :has() 偽類的瀏覽器支援表。
一旦你確定了你將使用的不被普遍支援的技術列表,最好研究一下它們在哪些瀏覽器中受支援,以及哪些相關技術有用。請參閱下面的 尋求幫助。
HTML 回退行為
有些問題可以透過利用 HTML/CSS 的自然工作方式來解決。
未識別的 HTML 元素被瀏覽器視為匿名行內元素(實際上是沒有語義值的行內元素,類似於 <span> 元素)。你仍然可以透過它們的名稱引用它們,並用 CSS 為它們設定樣式,例如——你只需要確保它們按你希望的方式執行。像為其他任何元素設定樣式一樣,包括在需要時將 display 屬性設定為 inline 以外的值。
更復雜的元素,如 HTML <video>、<audio>、<picture>、<object> 和 <canvas>(以及其他功能)都有自然的機制來添加回退,以防連結的資源不受支援。你可以在開始和結束標籤之間添加回退內容,不支援的瀏覽器將有效地忽略外部元素並執行巢狀內容。
例如
<video id="video" controls preload="metadata" poster="img/poster.jpg">
<source
src="video/tears-of-steel-battle-clip-medium.webm"
type="video/webm" />
<!-- Offer download -->
<p>
Your browser does not support WebM video; here is a link to
<a href="video/tears-of-steel-battle-clip-medium.mp4"
>view the video directly</a
>
</p>
</video>
此示例包含一個簡單的連結,允許你在 HTML 影片播放器甚至無法工作時下載影片,這樣至少使用者仍然可以訪問影片。
另一個例子是表單元素。當引入新的 <input> 型別用於在表單中輸入特定資訊(如時間、日期、顏色、數字等)時,如果瀏覽器不支援新功能,瀏覽器會使用 type="text" 的預設值。新增的輸入型別非常有用,尤其是在移動平臺上,提供一種無痛的資料輸入方式對使用者體驗非常重要。平臺根據輸入型別提供不同的 UI 小部件,例如用於輸入日期的日曆小部件。如果瀏覽器不支援某種輸入型別,使用者仍然可以輸入所需資料。
以下示例顯示日期和時間輸入
<form>
<div>
<label for="date">Enter a date:</label>
<input id="date" type="date" />
</div>
<div>
<label for="time">Enter a time:</label>
<input id="time" type="time" />
</div>
</form>
此程式碼的輸出如下
你可以按 播放 按鈕在 MDN Playground 中開啟示例並編輯原始碼。
如果你檢視示例,你將在嘗試輸入資料時看到 UI 功能正在執行。在具有動態鍵盤的裝置上,將顯示特定型別的鍵盤。在不支援的瀏覽器中,輸入將僅預設為普通文字輸入,這意味著使用者仍然可以輸入正確的資訊。
CSS 回退行為
CSS 在回退方面可以說比 HTML 更好。如果瀏覽器遇到它不理解的宣告或規則,它只會完全跳過它,而不會應用它或丟擲錯誤。如果這樣的錯誤溜進生產程式碼,這可能會讓你和你的使用者感到沮喪,但至少這意味著整個站點不會因為一個錯誤而崩潰,而且如果巧妙地使用,你可以利用它。
讓我們看一個例子——一個用 CSS 樣式化的簡單盒子,它有一些由各種 CSS 功能提供的樣式
你可以按 播放 按鈕在 MDN Playground 中開啟示例並使用原始碼。
該按鈕應用了許多宣告,但我們最感興趣的是以下這些
button {
/* … */
background-color: red;
background-color: rgb(255 0 0 / 90%);
box-shadow:
inset 3px 3px 3px rgb(255 255 255 / 40%),
inset -3px -3px 3px rgb(0 0 0 / 40%);
}
button:hover,
button:focus {
background-color: rgb(255 0 0 / 50%);
}
button:active {
box-shadow:
inset 3px 3px 3px rgb(0 0 0 / 40%),
inset -3px -3px 3px rgb(255 255 255 / 40%);
}
這裡我們提供了一個 RGB background-color,它在懸停時會改變不透明度,以提示使用者該按鈕是互動式的,以及一些半透明的內嵌 box-shadow 陰影,為按鈕增加一點紋理和深度。雖然現在已完全支援,但 RGB 顏色和盒子陰影並非一直存在;它們從 IE9 開始出現。不支援 RGB 顏色的瀏覽器會忽略該宣告,這意味著在舊瀏覽器中背景根本不會顯示,因此文字將無法閱讀,這很糟糕!

為了解決這個問題,我們添加了第二個 background-color 宣告,它只指定了 red 顏色關鍵字——這在非常舊的瀏覽器中很早就得到了支援,如果現代炫酷功能不起作用,它就充當回退。發生的情況是,訪問此頁面的瀏覽器首先應用第一個 background-color 值;當它到達第二個 background-color 宣告時,如果它支援 RGB 顏色,它將用此值覆蓋初始值。如果不支援,它將只忽略整個宣告並繼續。
注意:對於其他 CSS 功能,如 媒體查詢、@font-face 和 @supports 塊,情況也是如此——如果它們不受支援,瀏覽器會直接忽略它們。
選擇器支援
當然,如果你沒有使用正確的 選擇器 來選擇你想要樣式化的元素,那麼任何 CSS 功能都不會應用!
在一個逗號分隔的選擇器列表中,如果你只是錯誤地編寫了一個選擇器,它可能無法匹配任何元素。但是,如果一個選擇器無效,則整個選擇器列表都會被忽略,以及整個樣式塊。因此,只在一個寬容選擇器列表中包含一個 :-moz- 字首的偽類或偽元素,例如 :where(::-moz-thumb)。不要在 :is() 或 :where() 寬容選擇器列表之外的逗號分隔選擇器組中包含 :-moz- 字首的偽類或偽元素,因為除 Firefox 之外的所有瀏覽器都將忽略整個塊。請注意,:is() 和 :where() 都可以作為引數傳遞給其他選擇器列表,包括 :has() 和 :not()。
我們發現,使用瀏覽器開發工具檢查你嘗試樣式化的元素,然後檢視 DOM 檢查器通常提供的 DOM 樹麵包屑路徑,以檢視你的選擇器是否與其匹配,這很有幫助。
例如,在 Firefox 開發者工具中,你在 DOM 檢查器底部會得到這種輸出
![]()
如果例如你正在嘗試使用此選擇器,你將能夠看到它不會按預期選擇輸入元素
form > #date {
/* … */
}
(date 表單輸入不是 <form> 的直接子元素;你最好使用通用後代選擇器而不是子選擇器)。
處理 CSS 字首
另一組問題來自 CSS 字首——這些字首最初是一種機制,允許瀏覽器供應商在技術處於實驗階段時實現自己的 CSS(或 JavaScript)功能版本,這樣他們就可以在不與其他瀏覽器實現或最終無字首實現衝突的情況下進行試驗和完善。
例如,Firefox 使用 -moz-,Chrome/Edge/Opera/Safari 使用 -webkit-。在舊程式碼中你可能會遇到並可以安全移除的其他字首包括 -ms-(Internet Explorer 和早期版本 Edge 使用)和 -o(Opera 早期版本使用)。
帶字首的功能從未被打算用於生產網站——它們可能會在不事先警告的情況下更改或移除,可能會在需要它們的老舊瀏覽器版本中導致效能問題,並且一直是跨瀏覽器問題的根源。這尤其是一個問題,例如,當開發人員決定只使用屬性的 -webkit- 版本時,這意味著網站在其他瀏覽器中將無法工作。這種情況實際上發生得如此之多,以至於其他瀏覽器供應商也實現了幾個 CSS 屬性的 -webkit- 字首版本。雖然瀏覽器仍然支援一些帶字首的屬性名稱、屬性值和偽類,但現在實驗性功能被放在標誌後面,以便 Web 開發人員可以在開發過程中測試它們。
如果使用字首,請確保它確實需要;該屬性是少數仍需要字首的功能之一。你可以在 MDN 參考頁面和像 caniuse.com 這樣的網站上查詢哪些瀏覽器需要字首。如果你不確定,你也可以透過直接在瀏覽器中進行一些測試來找出答案。在帶字首的樣式宣告之後包含標準無字首版本;如果不支援,它將被忽略,如果支援,則會使用它。
.masked {
-webkit-mask-image: url("MDN.svg");
mask-image: url("MDN.svg");
-webkit-mask-size: 50%;
mask-size: 50%;
}
嘗試這個簡單的例子
-
使用此頁面或另一個帶有突出標題或其他塊級元素的站點。
-
在相關元素上右鍵/Cmd + 點選,然後選擇“檢查”/“檢查元素”(或你的瀏覽器中的相應選項)——這應該會在你的瀏覽器中開啟開發者工具,並在 DOM 檢查器中突出顯示該元素。
-
尋找一個可用於選擇該元素的功能。例如,在撰寫本文時,MDN 上的這個頁面有一個 ID 為
mdn-docs-logo的標誌。 -
將此元素的引用儲存在一個變數中,例如
jsconst test = document.getElementById("mdn-docs-logo"); -
現在嘗試為該元素上你感興趣的 CSS 屬性設定一個新值;你可以使用元素的 style 屬性來做到這一點,例如嘗試將這些內容輸入到 JavaScript 控制檯中
jstest.style.transform = "rotate(90deg)";
當你在第二個點後開始輸入屬性名稱表示時(請注意,在 JavaScript 中,CSS 屬性名稱以 小駝峰命名法 編寫,而不是 中劃線命名法),JavaScript 控制檯應該開始自動完成瀏覽器中存在的屬性名稱並匹配你目前已輸入的內容。這對於查詢該瀏覽器中實現了哪些屬性非常有用。
如果你確實需要包含現代功能,請使用 @supports 測試功能支援,它允許你實現本機功能檢測測試,並將帶字首或新功能巢狀在 @supports 塊中。
響應式設計問題
響應式設計是建立能夠適應不同裝置外形(例如,不同的螢幕寬度、方向(縱向或橫向)或解析度)的網頁佈局的實踐。例如,桌面佈局在移動裝置上檢視時會顯得很糟糕,因此你需要使用 媒體查詢 提供合適的移動佈局,並確保使用 視口 正確應用。你可以在 我們的響應式設計教程 中找到此類實踐的詳細說明。
解析度也是一個大問題——例如,移動裝置比臺式電腦更不可能需要大而重的影像,而且更有可能擁有較慢的網際網路連線,甚至可能昂貴的資料套餐,這使得浪費頻寬成為一個更大的問題。此外,不同的裝置可以有不同的解析度範圍,這意味著較小的影像可能會出現畫素化。有許多技術可以解決這些問題,從 媒體查詢 到更復雜的 響應式影像技術,包括 <picture> 元素和 <img> 元素的 srcset 和 sizes 屬性。
尋求幫助
你會遇到許多其他 HTML 和 CSS 問題,因此瞭解如何線上查詢答案變得非常寶貴。
最好的支援資訊來源包括 Mozilla 開發者網路(你現在就在這裡!)、stackoverflow.com 和 caniuse.com。
要使用 Mozilla 開發者網路 (MDN),大多數人會在搜尋引擎中搜索他們想要查詢資訊的技術,加上“mdn”一詞,例如“mdn HTML 影片”。MDN 包含幾種有用的內容型別
- 包含客戶端 Web 技術瀏覽器支援資訊的參考資料,例如 <video> 參考頁面。
- 其他支援參考資料,例如我們的 Web 媒體型別和格式指南,
- 解決特定問題的有用教程,例如 建立跨瀏覽器影片播放器。
caniuse.com 提供支援資訊,以及一些有用的外部資源連結。例如,請參見 https://caniuse.com/#search=video(你只需在文字框中輸入你正在搜尋的功能)。
stackoverflow.com (SO) 是一個論壇網站,你可以在其中提問,並讓其他開發人員分享他們的解決方案,查詢以前的帖子,並幫助其他開發人員。建議你在釋出新問題之前,先檢視是否已有你問題的答案。例如,我們在 SO 上搜索“停用 HTML 對話方塊上的自動對焦”,很快就找到了 停用 showModal 自動對焦使用 HTML 屬性。
除此之外,嘗試在你喜歡的搜尋引擎中搜索你問題的答案。如果遇到特定的錯誤訊息,搜尋它們通常很有用——其他開發人員很可能也遇到過和你相同的問題。
總結
現在你應該熟悉在 Web 開發中會遇到的主要型別的跨瀏覽器 HTML 和 CSS 問題,以及如何著手解決它們。