likes
comments
collection
share

纯 CSS 打造炫酷自定义范围滑块:无需 JavaScript,也能玩转样式!这篇文章将向你展示如何使用现代 CSS 技

作者站长头像
站长
· 阅读数 28

这篇文章将向你展示如何使用现代 CSS 技术,仅用原生 HTML <input> 元素创建一个吸睛的自定义范围滑块。

纯 CSS 打造炫酷自定义范围滑块:无需 JavaScript,也能玩转样式!这篇文章将向你展示如何使用现代 CSS 技

范围输入元素的结构

首先,我们来分析一下范围输入元素的结构。它是一个原生元素,每个浏览器都有自己的实现方式。主要有两种不同的实现:

一种用于 Webkit 和 Blink 浏览器,如 Chrome、Edge、Safari 和 Opera:

<input type="range" min="0" max="100" step="1" value="20">
  <div>
    <div pseudo="-webkit-slider-runnable-track" id="track">
      <div id="thumb">
    </div>
   </div>
  </div>
</input> 

纯 CSS 打造炫酷自定义范围滑块:无需 JavaScript,也能玩转样式!这篇文章将向你展示如何使用现代 CSS 技

另一种用于 Firefox:

<input type="range" min="0" max="100" step="1" value="20">
  <div></div>
  <div></div>
  <div></div>
</input> 

纯 CSS 打造炫酷自定义范围滑块:无需 JavaScript,也能玩转样式!这篇文章将向你展示如何使用现代 CSS 技

还有一种用于 IE 的实现,但好在 IE 浏览器现在已经基本消失了!

浏览器之间的这种不一致性使得这项任务变得困难,因为我们需要为每种实现提供不同的样式。我不会深入探讨这个问题,否则这篇文章就写不完了,但我强烈建议你阅读 Ana Tudor 的 这篇文章,以进行更深入的探索。

你需要记住的是,无论实现方式如何,我们总是有一个共同的组件:“滑块”

纯 CSS 打造炫酷自定义范围滑块:无需 JavaScript,也能玩转样式!这篇文章将向你展示如何使用现代 CSS 技

我只打算为这个元素设置样式,这将使我的自定义范围滑块易于定制。让我们直接进入代码,看看其中的奥妙。

自定义输入元素

第一步是使用 appearance: none 和其他一些常见属性来重置和禁用所有浏览器的默认样式:

input {
  appearance: none;
  background: none;
  cursor: pointer;
} 

在更复杂的情况下,我们可能需要添加更多代码,以防其他默认样式应用于我们的元素。只需确保我们有一个“裸”元素,没有任何视觉样式。

我们还定义了一些 CSS 变量,以便我们可以轻松地为范围滑块创建不同的变体:

input {
  --c: orange; /* 活动颜色 */
  --g: 8px; /* 间隙 */
  --l: 5px; /* 线宽 */
  --s: 30px; /* 滑块大小 */

  width: 400px; /* 输入宽度 */
  height: var(--s); 
  appearance: none;
  background: none;
  cursor: pointer;
} 

在这一步,只有滑块及其默认样式是可见的。

为滑块元素添加样式

让我们为滑块元素添加样式。我们将从基本设置开始:

<thumb selector> {
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  appearance: none;
} 

代码应该是不言自明的。到目前为止,还没有什么花哨的东西,我们会得到如下所示的结果。

请注意使用两个不同的选择器,正如我们在第一部分中解释的那样:

/* Chrome, Edge, Safari, Opera */
input[type="range" i]::-webkit-slider-thumb { }
/* Firefox */
input[type="range"]::-moz-range-thumb { } 

但是如何知道要使用哪个选择器呢?

我只是使用浏览器的开发者工具检查了输入的代码,看看每个浏览器都使用什么选择器来设置滑块的样式。我之前 分享的文章 向你展示了如何操作开发者工具来获取此类信息。

使用 border-image 添加一些魔法

现在,我们将使用一个神奇的 CSS 技巧来完成我们的滑块。它涉及使用 border-image

border-image: linear-gradient(90deg,var(--c) 50%,#ababab 0) 1/0 100vw/0 calc(100vw + var(--g)); 

我知道它看起来很吓人,但让我们剖析一下这行代码,你会发现它并不难。上面是以下代码的简写:

border-image-source: linear-gradient(90deg,var(--c) 50%,#ababab 0); 
border-image-slice: 1;
border-image-width: 0 100vw;
border-image-outset: 0 calc(100vw + var(--g)); 

MDN 页面 我们可以读到:

CSS 属性 border-image 在给定元素周围绘制图像。它替换了元素的常规边框。

我们的图像将是一个具有两种颜色的渐变——主要颜色(由 --c 定义)和灰色。我们需要边框图像水平覆盖输入的整个空间,因此我们为左右宽度使用一个较大的值 (100vw),同时将上下保持为 (0)。

但是 border-image-width 受限于元素大小。为了克服这个问题,我们还需要为 border-image-outset 使用一个较大的值,以增加边框图像的可用空间。再次来自 MDN

CSS 属性 border-image-outset 设置元素的边框图像从其边框框中设置出的距离。

使用 border-image-outset 在元素边框框外部渲染的边框图像部分不会触发溢出滚动条,也不会捕获鼠标事件。

当你第一次看到滑块时,它看起来像是我们在左边增加主色,但实际上我们是在滑动一个超出我们元素的固定渐变。

通过向输入元素添加 overflow: hidden 并使用一个较大的值,幻觉是完美的。

如果你想深入了解 border-image 并了解更多关于“宽度”和“外延”的内容,请查看 我的文章,我在其中剖析了 border-image 属性,以便了解它的所有秘密并理解我正在使用的值。

就这样!我们用几行代码创建了一个自定义范围滑块,你可以通过调整几个变量轻松控制它。

演示:codepen.io/SitePoint/p…

纯 CSS 打造炫酷自定义范围滑块:无需 JavaScript,也能玩转样式!这篇文章将向你展示如何使用现代 CSS 技

<input type="range" min="0" max="100" step="1" value="20">

<input type="range" min="0" max="100" step="1" style="--c: lightblue;--l: 6px;--g:12px;">

<input type="range" min="0" max="100" step="1" value="70" style="--c: red;--l: 4px;">
input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}

/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image: linear-gradient(90deg,var(--c) 50%,#ababab 0) 0 1/calc(50% - var(--l)/2) 100vw/0 calc(100vw + var(--g));
  -webkit-appearance: none;
  appearance: none;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--l) inset var(--c);
  border-image: linear-gradient(90deg,var(--c) 50%,#ababab 0) 0 1/calc(50% - var(--l)/2) 100vw/0 calc(100vw + var(--g));
  -moz-appearance: none;
  appearance: none;
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

添加一些动画

当我们与滑块交互时,添加一些微妙的动画怎么样?它不需要很多代码,并且可以增强滑块的用户体验。

首先,当我们点击滑块时,我们将把滑块从一个只有边框的圆形变成一个完整的圆形。为此,我们增加 box-shadow 的扩展值。请记住,我们使用 box-shadow 来定义滑块的边框:

box-shadow: 0 0 0 var(--l) inset var(--c); 

我们使用 :active 选择器和 :focus-visiblevar(--l) 更新为 var(--s)。后者与键盘导航有关,并允许我们无论使用鼠标还是键盘都能获得相同的效果。

代码如下:

input[type="range" i]::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--l) inset var(--c);
  transition: .3s;
}

input[type="range" i]::-moz-range-thumb {
  box-shadow: 0 0 0 var(--l) inset var(--c);
  transition: .3s;
}

input:active::-webkit-slider-thumb,
input:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--s) inset var(--c);
}

input:active::-moz-range-thumb,
input:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 var(--s) inset var(--c);
} 

对于 box-shadow 过渡来说,它有点冗长,对吧?我们可以使用 CSS 变量来优化它:

input[type="range" i]::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--c);
  transition: .3s;
}

input[type="range" i]::-moz-range-thumb {
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--c);
  transition: .3s;
}

input:active,
input:focus-visible {
  --_b:  var(--s);
} 

我使用一个变量来表示扩展值,我只是在 :active:focus-visible 上更新该变量。

我还将为颜色添加一点动画。我会在 :hover 上使其颜色更深一点。为此,我不会更新颜色,而是使用新的 color-mix() 函数将其与黑色混合。这个技巧允许我们使用由 --c 定义的主色,而不用为每个滑块手动定义新的深色:

--_c: color-mix(in srgb, var(--c), #000 var(--p,0%)); 

我定义了一个新的变量来替换代码中的 --c。然后,通过使用变量 --p 调整黑色 (#000) 的百分比,我就可以控制颜色的“暗度”:

input:focus-visible,
input:hover{
  --p: 25%;
} 

这个功能还没有在所有浏览器中得到支持,因此强烈建议使用回退方案:

@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c); /* 如果不支持,我们将保持颜色不变 */
  }
} 

我们的范围滑块现在完美了!

纯 CSS 打造炫酷自定义范围滑块:无需 JavaScript,也能玩转样式!这篇文章将向你展示如何使用现代 CSS 技

input {
  --c: orange; /* active color */
  --g: 8px; /* the gap */
  --l: 5px; /* line thickness*/
  --s: 30px; /* thumb size*/
  
  width: 400px;
  height: var(--s); /* needed for Firefox*/
  --_c: color-mix(in srgb, var(--c), #000 var(--p,0%));
  -webkit-appearance :none;
  -moz-appearance :none;
  appearance :none;
  background: none;
  cursor: pointer;
  overflow: hidden;
}
input:focus-visible,
input:hover{
  --p: 25%;
}
input:active,
input:focus-visible{
  --_b: var(--s)
}
/* chromium */
input[type="range" i]::-webkit-slider-thumb{
  height: var(--s);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 0 1/calc(50% - var(--l)/2) 100vw/0 calc(100vw + var(--g));
  -webkit-appearance: none;
  appearance: none;
  transition: .3s;
}
/* Firefox */
input[type="range"]::-moz-range-thumb {
  height: var(--s);
  width: var(--s);
  background: none;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--_b,var(--l)) inset var(--_c);
  border-image: linear-gradient(90deg,var(--_c) 50%,#ababab 0) 0 1/calc(50% - var(--l)/2) 100vw/0 calc(100vw + var(--g));
  -moz-appearance: none;
  appearance: none;
  transition: .3s;
}
@supports not (color: color-mix(in srgb,red,red)) {
  input {
    --_c: var(--c);
  }
}


/**/
body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  gap: 40px;
  place-content: center;
  background: repeating-linear-gradient(-45deg, #fff 0 20px, #f9f9f9 0 40px)
}

结论

我们已经完成了,而且不必处理任何与浏览器相关的复杂实现!我们确定了滑块元素的选择器,并使用一些 CSS 技巧,用它设置了整个范围滑块的样式。别忘了,我们只使用了 <input> 元素执行此操作。

以下是一些使用相同技巧的滑块示例。我将把剖析它们的代码作为练习留给你。

演示1:codepen.io/t_afif/pen/…

纯 CSS 打造炫酷自定义范围滑块:无需 JavaScript,也能玩转样式!这篇文章将向你展示如何使用现代 CSS 技

演示2:codepen.io/t_afif/pen/…

纯 CSS 打造炫酷自定义范围滑块:无需 JavaScript,也能玩转样式!这篇文章将向你展示如何使用现代 CSS 技

转载自:https://juejin.cn/post/7403627317334147098
评论
请登录