創建在所有瀏覽器中看起來一致的自定義範圍輸入

已發表: 2022-03-10
快速總結 ↬範圍輸入是出了名的風格痛苦。 每個瀏覽器都以不同的方式呈現輸入,要求您使用供應商前綴來創建有凝聚力的外觀和感覺。 在本文中,我們將了解 HTML 範圍輸入的古怪之處,並演示如何設置輸入樣式以在所有主要瀏覽器中看起來一致。

作為 UI 組件庫的維護者之一,我已經實現並設置了無數輸入元素的樣式。 有一天,我被分配了向庫中添加範圍輸入的任務,我認為這將是與我過去實現的其他輸入類似的過程。 這個假設是正確的,直到我開始跨多個瀏覽器測試範圍輸入並很快意識到我手頭還有很多工作要做。

經過大量研究,我終於能夠確定足夠多的博客文章、文章和深入的教程來幫助我設置範圍輸入的樣式以一致地呈現。 無需四處搜索多種資源,這篇博文的目的是提供一個一站式商店,用於學習如何正確設置在所有瀏覽器中看起來一致的範圍輸入樣式。 當我不得不自己做這件事時,我希望我有這篇文章,我希望它有助於使這個過程對你來說更快、更順暢。

範圍輸入的剖析

範圍輸入包括兩個主要部分:

  1. 追踪
    這是拇指沿滑塊運行的部分。 或者換一種說法,它是代表可以選擇的值範圍的長元素。
  2. 拇指
    這是軌道上的一個元素,用戶可以四處移動以選擇不同的範圍值。
範圍輸入由軌道和拇指組成。
範圍輸入由軌道和拇指組成。 (大預覽)

如果它是一個數學方程:

範圍輸入 = 軌道 + 拇指

範圍輸入有時被稱為“滑塊”,在本文的其餘部分,我將交替使用這些術語。

瀏覽器不一致

為了說明為什麼我們首先需要關於樣式範圍輸入的教程,我們將看一些默認 HTML 範圍輸入的屏幕截圖,以及它是如何在四種主要瀏覽器(Chrome、Firefox、Safari 和邊緣)。 或者,如果您願意,您可以在各個瀏覽器中查看此 CodeSandbox 演示,以查看瀏覽器的不一致之處。

注意:這些屏幕截圖是在 2021 年 9 月拍攝的,可能會隨著相應瀏覽器的更新而發生變化。

讓我們從 Chrome 開始,在我看來,它默認呈現最用戶友好的輸入版本。

默認 HTML 範圍輸入的 Chrome 演示
默認 HTML 範圍輸入的 Chrome 演示。 (大預覽)

接下來是 Firefox,它看起來與 Chrome 呈現的輸入不同。 在 Firefox 中,軌道的高度略短。 另一方面,拇指的高度和寬度更大,並且沒有與 Chrome 版本相同的藍色背景顏色。

默認 HTML 範圍輸入的 Firefox 演示
默認 HTML 範圍輸入的 Firefox 演示。 (大預覽)

Safari 滑塊在外觀上與 Firefox 版本最接近,但它仍然不同。 這次在軌道周圍似乎有一個陰影效果,拇指的高度和寬度比 Chrome 和 Firefox 的再現要小。 如果您仔細觀察,您還可以看到拇指並未直接位於軌道的中心,從而使其外​​觀和感覺粗糙。

默認 HTML 範圍輸入的 Safari 演示
默認 HTML 範圍輸入的 Safari 演示。 (大預覽)

最後但並非最不重要的是 Edge,現在 Microsoft Edge 是基於 Chromium 構建的,與其他三種瀏覽器相比,它與 Chromium 之前的前身相比更加一致。 但是,我們可以看到它的呈現方式仍然與其他三個瀏覽器不同。 Edge 對其範圍輸入的再現看起來與 Chrome 版本非常相似,只是它的拇指和拇指之前的軌道左側具有更深的灰色背景色。

默認 HTML 範圍輸入的邊緣演示
默認 HTML 範圍輸入的邊緣演示。 (大預覽)

既然我們已經看到了每個瀏覽器呈現範圍輸入的非常不一致,我們將看看如何使用 CSS 來統一它們。

跳躍後更多! 繼續往下看↓

範圍重置(基線樣式)

因為瀏覽器的不一致性變化如此之大,我們需要從一個公平的競爭環境開始。 一旦刪除了每個瀏覽器應用的默認樣式,我們就可以開始努力製作更統一的輸入。 我們將使用input[type="range"]元素屬性選擇器,此處應用的樣式將類似於輸入的 CSS 重置。

要應用基線樣式,我們需要四個屬性:

  1. -webkit-appearance: none;
    此屬性是適用於所有主要瀏覽器的供應商前綴。 通過賦予它none的值,這會告訴每個相應的瀏覽器清除任何默認樣式。 這使我們能夠從頭開始並從那時起構建輸入的外觀。
  2. background: transparent;
    這將清除應用於輸入的默認背景。
  3. cursor: pointer;
  4. width
    設置輸入的整體寬度。
 input[type="range"] { -webkit-appearance: none; appearance: none; background: transparent; cursor: pointer; width: 15rem; }
背景之前 Chrome 中的範圍輸入:應用透明。
背景之前 Chrome 中的範圍輸入:應用透明。 (大預覽)
應用所有重置樣式後,Chrome 中的範圍輸入。
應用所有重置樣式後,Chrome 中的範圍輸入。 (大預覽)

為賽道造型

在為軌道(和拇指)設置樣式時,我們需要針對不同的瀏覽器特定的供應商前綴,以便在相關元素中應用正確的樣式。 展望未來,任何以-webkit為前綴的偽元素都將應用於 Chrome、Safari、Opera 和 Edge(Chromium 後)瀏覽器。 任何以-moz為前綴的東西都與 Firefox 相關。

以下是我們將用於定位軌道的偽元素:

  • ::-webkit-slider-runnable-track
    針對 Chrome、Safari 和 Edge Chromium 中的軌道
  • ::-moz-range-track
    以 Firefox 中的軌道為目標。
 /***** Track Styles *****/ /***** Chrome, Safari, Opera, and Edge Chromium *****/ input[type="range"]::-webkit-slider-runnable-track { background: #053a5f; height: 0.5rem; } /******** Firefox ********/ input[type="range"]::-moz-range-track { background: #053a5f; height: 0.5rem; }

軌道唯一需要的屬性是heightbackground 。 但是,通常會看到應用border-radius以使邊緣變圓。

應用軌道樣式後,Firefox 中的範圍輸入。
應用軌道樣式後,Firefox 中的範圍輸入。 (大預覽)

為拇指造型

設置拇指(用戶移動的中間旋鈕)的樣式需要考慮更多的細微差別,因為在範圍輸入的那部分瀏覽器之間存在更多的不一致。

以下是我們將用於定位拇指的偽元素:

  • ::-webkit-slider-thumb
    在 Chrome、Safari 和 Edge Chromium 中定位拇指
  • ::-moz-range-thumb
    以 Firefox 中的拇指為目標。

由於 Firefox 和 Webkit 瀏覽器有不同的樣式問題,我將分別解決每個問題並演示如何處理應用於拇指的每個古怪的默認值。

Chrome、Safari、Edge Chromium (Webkit)

我們需要應用到::-webkit-slider-thumb偽元素的第一個樣式是-webkit-appearance: none; 供應商前綴。 我們在“基線樣式”部分中使用了這個屬性來覆蓋瀏覽器應用的一般默認樣式,它在拇指上也有類似的用途。

應用 <code>-webkit-appearance: none;</code> 後 Chrome 中的範圍輸入
-webkit-appearance: none; 被申請;被應用。 (大預覽)

一旦刪除了默認樣式,我們就可以應用我們自己的自定義樣式。 假設我們將heightwidthbackground-color應用到拇指上,下面是我們目前所擁有的示例:

具有自定義拇指樣式的 Chrome 中的範圍輸入。
具有自定義拇指樣式的 Chrome 中的範圍輸入。 (大預覽)

默認情況下,WebKit 瀏覽器會渲染拇指,使其不在軌道的中心。

為了使拇指在軌道上正確居中,我們可以使用以下公式並將其應用於margin-top屬性:

margin-top = (軌道高度,以像素為單位/2) - (拇指高度,以像素為單位/2)

採用我們在前面部分中應用的樣式並將rems轉換為像素,我們將有 8px 的軌道高度和 32px 的拇指高度。 這意味著:

邊距頂部 = (8/2) - (32/2) = 4 - 16 = -12px

基於此,我們最終確定的 webkit 瀏覽器樣式將類似於以下代碼塊:

 /***** Thumb Styles *****/ /***** Chrome, Safari, Opera, and Edge Chromium *****/ input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; /* Override default look */ appearance: none; margin-top: -12px; /* Centers thumb on the track */ background-color: #5cd5eb; height: 2rem; width: 1rem; }
應用所有樣式後,Chrome 中的範圍輸入。
應用所有樣式後,Chrome 中的範圍輸入。 (大預覽)

火狐

在 Firefox 中將樣式應用於拇指時,您需要利用::-moz-range-thumb偽元素。 值得慶幸的是,Firefox 沒有遭受與 Webkit 瀏覽器相同的居中問題。 但是,它的一個問題是它適用於拇指的默認邊框半徑和灰色邊框。

Firefox 中的範圍輸入,默認應用灰色邊框和邊框半徑。
(大預覽)

為了修復默認的灰色邊框,我們可以添加border: none; 財產。 要刪除應用的默認邊框半徑,我們可以添加border-radius: 0屬性,現在拇指將在所有瀏覽器中看起來一致。

基於此,我們最終確定的 Firefox 瀏覽器樣式如下所示:

 /***** Thumb Styles *****/ /***** Firefox *****/ input[type="range"]::-moz-range-thumb { border: none; /*Removes extra border that FF applies*/ border-radius: 0; /*Removes default border-radius that FF applies*/ background-color: #5cd5eb; height: 2rem; width: 1rem; }

注意: Webkit 瀏覽器不會自動將此半徑應用於邊框,因此如果您發現您確實想要將某種形式的邊框半徑應用於拇指,而不是像我們上面所做的那樣取消它,您將需要將所需的border-radius尺寸應用於-webkit-slider-thumb::-moz-range-thumb偽元素。

焦點風格

因為範圍輸入是一個交互式元素,所以必須添加焦點樣式以符合可訪問性最佳實踐和標準。 當應用焦點樣式時,它為用戶提供了一個視覺指示器,對於那些使用鍵盤導航頁面的人來說尤其重要。

根據 WAI-ARIA: Slider 文檔,建議:

焦點位於滑塊(鼠標用戶將移動的視覺對象,也稱為拇指)上。

我們要做的第一件事是刪除默認的焦點樣式,以便我們可以用自定義樣式覆蓋它們。 為了定位拇指焦點樣式,我們可以利用我們在上一節中使用的::-webkit-slider-thumb::-moz-range-thumb偽元素,並將它們與:focus偽類結合起來. 然後我們可以使用 CSS 的 outline 和 outline-offset 屬性來設置我們想要的樣式。

 /***** Focus Styles *****/ /* Removes default focus */ input[type="range"]:focus { outline: none; } /***** Chrome, Safari, Opera, and Edge Chromium *****/ input[type="range"]:focus::-webkit-slider-thumb { border: 1px solid #053a5f; outline: 3px solid #053a5f; outline-offset: 0.125rem; } /******** Firefox ********/ input[type="range"]:focus::-moz-range-thumb { border: 1px solid #053a5f; outline: 3px solid #053a5f; outline-offset: 0.125rem; }

注意如果將border-radius應用於拇指,Firefox 會呈現拇指形狀的輪廓,而其他瀏覽器會顯示塊狀輪廓。 不幸的是,沒有一個簡單的 CSS 修復方法,這是唯一存在的不一致。 但是,添加這些樣式的主要目的是出於可訪問性目的,並且仍然可以實現主要目標,即在元素聚焦時提供視覺指示器。

Chrome 中的範圍輸入,應用了自定義焦點樣式。
Chrome 中的範圍輸入,應用了自定義焦點樣式。 (大預覽)

把它們放在一起

現在我們已經介紹了統一範圍輸入所需的所有樣式,下面是最終的 CSS 樣式表的樣子:

 /********** Range Input Styles **********/ /*Range Reset*/ input[type="range"] { -webkit-appearance: none; appearance: none; background: transparent; cursor: pointer; width: 15rem; } /* Removes default focus */ input[type="range"]:focus { outline: none; } /***** Chrome, Safari, Opera and Edge Chromium styles *****/ /* slider track */ input[type="range"]::-webkit-slider-runnable-track { background-color: #053a5f; border-radius: 0.5rem; height: 0.5rem; } /* slider thumb */ input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; /* Override default look */ appearance: none; margin-top: -12px; /* Centers thumb on the track */ /*custom styles*/ background-color: #5cd5eb; height: 2rem; width: 1rem; } input[type="range"]:focus::-webkit-slider-thumb { border: 1px solid #053a5f; outline: 3px solid #053a5f; outline-offset: 0.125rem; } /******** Firefox styles ********/ /* slider track */ input[type="range"]::-moz-range-track { background-color: #053a5f; border-radius: 0.5rem; height: 0.5rem; } /* slider thumb */ input[type="range"]::-moz-range-thumb { border: none; /*Removes extra border that FF applies*/ border-radius: 0; /*Removes default border-radius that FF applies*/ /*custom styles*/ background-color: #5cd5eb; height: 2rem; width: 1rem; } input[type="range"]:focus::-moz-range-thumb { border: 1px solid #053a5f; outline: 3px solid #053a5f; outline-offset: 0.125rem; }

結論

除了本文中概述的方法之外,您還可以利用我創建的範圍輸入 CSS 生成器range-input.css 。 這個項目的關鍵是創建一個工具,使開發人員的這個過程更簡單。 CSS 生成器允許您快速設置常見 CSS 屬性的樣式,並提供一個演示滑塊,顯示您想要應用的樣式的實時預覽。

希望將來樣式範圍輸入會更簡單。 然而,在那一天到來之前,知道要定位哪些偽元素和供應商前綴將幫助您更好地設計滑塊以滿足您的需求。

Smashing 雜誌的更多資源

  • CSS 生成器
  • 使用accent-color簡化表單樣式
  • 針對常見 UI 挑戰的智能 CSS 解決方案
  • 深入研究 CSS 中的object-fitbackground-size