创建在所有浏览器中看起来一致的自定义范围输入

已发表: 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