CSS 实现带tooltip的slider

news2025/2/27 5:54:11

现代 CSS 强大的令人难以置信

这次我们来用 CSS 实现一个全功能的滑动输入器,也就是各大组件库都有的slider,效果如下

还可以改变一下样式,像这样

特别是在拖动时,tooltip还能跟随拖动的方向和速度呈现不同的倾斜角度,这些是如何通过CSS实现的呢?一起来看看吧~

一、自定义input range

首先来看滑动输入器的最原始形态

<input type="range">

效果如下

要自定义样式,一般要修改这几个伪元素

::-webkit-slider-container{
  /*容器*/
}
::-webkit-slider-runnable-track{
  /*轨道*/
}
::-webkit-slider-thumb{
  /*手柄*/
}

这里可以很轻松的改变轨道的宽高,拖拽手柄的大小等等

[type="range"] {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
    outline: 0;
    background-color: transparent;
    width: 400px;
    overflow: hidden;
    height: 20px;
}
[type="range"]::-webkit-slider-runnable-track {
    height: 4px;
    background: #eee;
    border-radius: 4px;
}
[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: #9747FF;
    transform: translateY(-50%);
    margin-top: 2px;
}

效果如下

相信大家很容易做到这一步,因为只需要自定义这几个伪元素就行了。

这里还有一个难点,就是左边滑过的区域,如何也自定义颜色呢?毕竟没有专门的选择器(Firefox有,这里主要讨论Chrome),接下来请继续看

二、自定义滑过区域的颜色

在之前,曾经通过border-image实现过类似的效果,主要原理是border-image可以在绘制元素之外,在拖拽手柄左侧绘制一个足够长的条条就行了

不过这种实现有一个局限,由于是通过超出隐藏的方式裁剪掉多出的部分,使得滑动条边缘是“一刀切”的,无法实现圆角

有兴趣的可以回顾之前这篇文章:纯 CSS 美化滑动输入条 input range

回到这里,可以想想,要实现自定义左边滑过区域的样式,本质是需要知道当前的滑动进度,假设进度是--progress,那么轨道滑过区域的背景色可以这样来表示

[type="range"]::-webkit-slider-runnable-track {
    height: 4px;
    background: linear-gradient(#9747FF 0 0) 0 0/calc(var(--progress) * 1%) 100% no-repeat #eee;
    border-radius: 4px;
}

那么,如何实时获取这个进度呢?

在以往,可以借助 JS实时更新这样一个自定义变量,这也是目前最好的实现方式

而现在,有了更好的方式来彻底实现这样一个功能,那就是滚动驱动动画。

CSS 滚动驱动动画终于正式支持了~

有些同学可能无法理解,这里又没有滚动,怎么会和这个特性有关呢?别急,滚动驱动有两种类型,一个是 scroll()、还有一个是view(),我们这里要用到的就是view(),其实也就是利用这一点来监听元素在视区的位置。

具体怎么做呢?

首先,通过@property定义一个CSS变量,整数类型

@property --progress {
    syntax: "<integer>";
    initial-value: 0;
    inherits: true;
}

然后定一个动画,从0100就行了,表示进度

@keyframes slider {
    to {
        --progress: 100;
    }
}

由于是需要监听拖拽手柄,也就是::-webkit-slider-thumb 的位置,所以要给这个伪元素添加view-timeline,但是我们需要通过::-webkit-slider-thumb改变父级轨道::-webkit-slider-runnable-track的样式,所以需要用到time-scope(可以跨层级关联),具体实现如下

[type="range"]{
    timeline-scope: --slider;
    animation: slider linear 3s reverse;
    animation-timeline: --slider;
}
[type="range"]::-webkit-slider-thumb {
    /**/
    view-timeline: --slider inline;
}

这样一来,拖拽手柄的位置就通过动画实时映射到了input 上,效果如下

这样就是实现了自定义滑动区域的样式,是不是非常神奇?

三、实时显示滑动进度

由于前面实现了--progress的实时变化,现在展示出来就比较容易了,需要用CSS计数器

为了方便表示,我们可以单独用一个标签来展示进度,结构如下

<label class="slider">
  <input type="range">
  <output class="tooltip"></output>
</label>

然后将--progress通过伪元素呈现出来

.tooltip::before{
  content: counter(num);
  counter-reset: num var(--progress);
}

效果如下

数字已经可以正常显示了,但是有个问题,起始点不对,不是0100,我们把拖拽手柄透明度降低,可以看到进度其实是这样的

这是由于默认的animation-rangecover,除了这种方式,还有其他几种方式

很明显,我们这里应该需要contain,因为滑块是始终在轨道内的

.slider{
    position: relative;
    timeline-scope: --slider;
    animation: slider linear 3s reverse;
    animation-timeline: --slider;
    animation-range: contain; /*设置animation-range*/
}

效果如下

这样进度就正常了

四、tooltip自动跟随滑块

首先美化一下,小三角可以用另一个伪元素实现

.tooltip{
  position: absolute;
  margin: 0 0 20px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  font-size: 14px;
  border-radius: 4px;
  padding: 10px;
  color: #f0f0f0;
  background-color: #333;
  transform-origin: center bottom;
  filter: drop-shadow(4px 4px 4px rgba(50, 50, 50, 0.3));
}
.tooltip::after{
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  margin-left: -5px;
  border-width: 5px;
  border-style: solid;
  border-color: black transparent transparent transparent;
}

效果如下

那么,如何让这个tooltip自动跟随滑块呢?

一种方式是直接通过--progress来计算left

.tooltip{
  position: absolute;
  left: calc(var(--progress) * 1%);
}

不过这种计算是有偏差的,这是因为定位是相对于轨道位置的,而不是滑块中心

为了修复这个问题,我们可以给input一个负的margin

[type="range"] {
    /*  */
    margin: 0 -10px;
}

这样就可以了

不过这样还有有尺寸方面的问题的,如下

除了这种方式,还可以用锚点定位的方式实现,有兴趣可以参考之前这篇文章:CSS 锚点定位终于来了!

实现非常简单,只需要给滑块一个anchor-name

[type="range"]::-webkit-slider-thumb {
    /**/
    anchor-name: --thumb;
}

然后给tooltip设置锚点定位

.tooltip{
  position: absolute;
  position-anchor: --thumb;
  inset-area: top;
}

这样就完美实现了,也不用担心定位偏差的问题

五、自动跟随拖拽方向

还有最后一个效果,可以自动跟随拖拽方向,这是如何实现的呢?其实在之前这篇文章中有详细讲解

纯 CSS 检测滚动的速度和方向

具体原理可以回顾这篇文章,这里简单介绍一下

重新定义一个CSS变量

@property --progress2 {
    syntax: "<integer>";
    initial-value: 0;
    inherits: true;
}

然后给这个变量设置为--progress,但是要给一个过渡时间

.tooltip{
  --progress2: var(--progress);
  transition: --progress2 .1s ease-out;
}

由于有过渡时间,所以这两个变量就会有一个差值,类似于这样

根据这个差值,我们不就可以知道拖动方向和速度了吗,然后给一个旋转角度

.tooltip{
  transform-origin: center bottom;
  rotate: calc((var(--progress2) - var(--progress))*2deg);
}

这样就实现了文章开头所示效果

完整代码可以查看以下链接

  • CSS slider (codepen.io)')点击预览

还可以改变一下样式

[type="range"]::-webkit-slider-runnable-track {
    height: 20px;
    background: linear-gradient(#9747FF 0 0) 0 0/calc(var(--progress) * 1% + 20px * (50 - var(--progress))/100) 100% no-repeat #eee;
    border-radius: 24px;
}
[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: #fff;
    border: 3px solid #9747FF;
    view-timeline: --slider inline;
    anchor-name: --thumb;
}

这样可以得到下面的效果

完整代码可以查看以下链接

  • CSS custom slider (codepen.io)')点击预览

六、兼容性和总结

这个实现主要依赖于滚动驱动动画,所以兼容性要求Chrome 115+,如果需要tooltip的锚点定位,则需要Chrome 125+,下面总结一下

  1. Chrome 没有专门的选择器来自定义滑过区域的样式
  2. 通过border-image可以自定义滑过区域的样式,但是不能实现圆角
  3. 滚动驱动动画的视图滚动可以监听滑块的位置
  4. 通过CSS变量和滚动驱动动画可以将实时进度传递给轨道,从而通过线性渐变绘制滑过区域颜色
  5. 借助CSS计数器和伪元素可以将CSS变量显示在页面

当然,不兼容的浏览器也可以采用回退措施,比如不支持滚动驱动动画,我们可以用JS来动态赋值--progress变量,不支持锚定定位,我们可以用绝对定位,配合left也能实现,虽然复杂一点,但也是现阶段比较好的处理方式了,剩下的就交给时间吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2261356.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MybatisPlus-扩展功能

代码生成 在使用MybatisPlus以后&#xff0c;基础的Mapper、Service、PO代码相对固定&#xff0c;重复编写也比较麻烦。因此MybatisPlus官方提供了代码生成器根据数据库表结构生成PO、Mapper、Service等相关代码。只不过代码生成器同样要编码使用&#xff0c;也很麻烦。 这里…

中后台管理信息系统:Axure12套高效原型设计框架模板全解析

中后台管理信息系统作为企业内部管理的核心支撑&#xff0c;其设计与实现对于提升企业的运营效率与决策能力具有至关重要的作用。为了满足多样化的中后台管理系统开发需求&#xff0c;一套全面、灵活的原型设计方案显得尤为重要。本文将深入探讨中后台管理信息系统通用原型方案…

40 基于单片机的温湿度检测判断系统

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52单片机&#xff0c;采用dht11温湿度传感器检测温湿度&#xff0c; 通过lcd1602显示屏各个参数&#xff0c;四个按键分别可以增加温湿度的阈值&#xff0c; 如果超过阈值&#xff0c;则…

SAP ABAP-日期格式问题 SAP内部错误,反序列化JSON字符串时发生异常 值 20241215 不是根据 ABAP 的 XML 格式的有效日期

SAP ABAP-日期格式问题 SAP内部错误,反序列化JSON字符串时发生异常 值 20241215 不是根据 ABAP 的 XML 格式的有效日期 在SAP内部用 YYYYMMDD没有问题 外部传入参数

深度学习——激活函数、损失函数、优化器

深度学习——激活函数、损失函数、优化器 1、激活函数1.1、一些常见的激活函数1.1.1、sigmoid1.1.2、softmax1.1.3、tanh1.1.4、ReLU1.1.5、Leaky ReLU1.1.6、PReLU1.1.7、GeLU1.1.8、ELU 1.2、激活函数的特点1.2.1、非线性1.2.2、几乎处处可微1.2.3、计算简单1.2.4、非饱和性1…

YOLOv5-7.0训练过程中出现报错Example: export GIT_PYTHON_REFRESH=quiet

出现报错&#xff1a; This initial message can be silenced or aggravated in the future by setting the $GIT_PYTHON_REFRESH environment variable. Use one of the following values: - quiet|q|silence|s|silent|none|n|0: for no message or exception - warn…

发布/部署WebApi服务器(IIS+.NET8+ASP.NETCore)

CS软件授权注册系统-发布/部署WebApi服务器(IIS.NET8ASP.NETCore) 目录 本文摘要VS2022配置发布VS2022发布WebApiIIS服务器部署WebApi 将程序文件复制到云服务器添加网站配置应用程序池配置dns域名配置端口阿里云ECS服务器配置19980端口配置https协议 (申请ssl证书)测试WebAp…

从零开始:如何在.NET Core Web API中完美配置Swagger文档

目录 新建项目 RestFul Swagger配置 注释展示 版本控制 Token传值 方法封装 新建项目 打开visual studio创建新项目&#xff0c;这里我们选择.net core web api模板&#xff0c;然后输入项目名称及其解决方案创建新项目 这里使用配置一些其他信息&#xff0c;根据自己情…

零基础开始学习鸿蒙开发-基础页面的设计

目录 1.样例图 2.逐项分析 2.1 头顶布局分析&#xff1a;首先我们要把第一行的图标绘制出来&#xff0c;一个左一个右&#xff0c;很明显&#xff0c;需要放在一个Row容器中&#xff0c;具体代码如下&#xff1a; 2.2 和头像同一行的布局&#xff0c;需要注意的是&#xff0c…

vscode借助插件调试OpenFoam的正确的.vscode配置文件

正确的备份文件位置&#xff1a; /home/jie/桌面/理解openfoam/正确的调试爆轰单进程案例/mydebugblastFoam 调试爆轰案例流体 并且工作区和用户区都是openfoam-7版本 问题&#xff1a;F5以debug模式启动后不停在断点 解决方法&#xff1a; 这里备份一下.vsode正确的配置&…

【小白包会的】使用supervisor 管理docker内多进程

使用supervisor 管理docker内多进程 一般情况下&#xff0c;一个docker是仅仅运行一个服务的 但是有的情况中&#xff0c;希望一个docker中运行多个进程&#xff0c;运行多个服务&#xff0c;也就是一个docker容器执行多个服务。 调研了一下&#xff0c;发现可以通过**super…

day11 性能测试(3)——Jmeter 断言+关联

【没有所谓的运气&#x1f36c;&#xff0c;只有绝对的努力✊】 目录 1、复习 2、查看结果树 多个http请求原因分析 3、作业 4、Jmeter断言 4.1 响应断言 4.1.1 案例 4.1.2 小结 4.2 json断言 4.2.1 案例 4.2.2 小结 4.3 断言持续时间 4.3.1 案例 4.3.2 小结 4.…

热更新解决方案3 —— xLua

概述 xLua框架导入和AB包相关准备 xLua导入 其它的导入 C#调用Lua 1.Lua解析器 using System.Collections; using System.Collections.Generic; using UnityEngine; //引用命名空间 using XLua;public class Lesson1_LuaEnv : MonoBehaviour {// Start is called before the fi…

Rk3588 FFmpeg 拉流 RTSP, 硬解码转RGB

RK3588 ,基于FFmpeg, 拉取RTSP,使用 h264_rkmpp 实现硬解码. ⚡️ RK3588 编译ffmpeg参考: Ubuntu x64 架构, 交叉编译aarch64 FFmpeg mpp Code RTSPvoid hardwave_init(AVCo

谷粒商城—分布式高级①.md

1. ELASTICSEARCH 1、安装elastic search dokcer中安装elastic search (1)下载ealastic search和kibana docker pull elasticsearch:7.6.2 docker pull kibana:7.6.2(2)配置 mkdir -p /mydata/elasticsearch/config mkdir -p /mydata/elasticsearch/data echo "h…

OpenCV圆形标定板检测算法findGrid原理详解

OpenCV的findGrid函数检测圆形标定板的流程如下: class CirclesGridClusterFinder {CirclesGridClusterFinder(const CirclesGridClusterFinder&); public:CirclesGridClusterFinder

30. Three.js案例-绘制并渲染圆弧

30. Three.js案例-绘制并渲染圆弧 实现效果 知识点 WebGLRenderer WebGLRenderer 是 Three.js 中用于渲染 3D 场景的核心类。它利用 WebGL 技术在浏览器中渲染 3D 图形。 构造器 new THREE.WebGLRenderer(parameters) 参数类型描述parametersObject可选参数对象&#xff…

STM32F407ZGT6-UCOSIII笔记4:时间片轮转调度

本文学习与程序编写基于 正点原子的 STM32F1 UCOS开发手册 编写熟悉一下 UCOSIII系统的 时间片轮转调度 文章提供测试代码讲解、完整工程下载、测试效果图 目录 解决上文的卡系统问题&#xff1a; 使能时间片轮转调度&#xff1a; 任务初始化定义更改&#xff1a; 文件结构…

谭浩强C++课后练习(更新中)

基于过程的程序设计 第1章 C的初步知识 1. 请根据你的了解&#xff0c;叙述C的特点。C对C有哪些发展? 2. 一个 C程序是由哪几部分构成的?其中的每一部分起什么作用? 3. 从接到一个任务到得到最终结果&#xff0c;一般要经过几个步骤? 4. 请说明编辑、编译、连接的作用…

单元测试知识总结

我们希望每段代码都是自测试的&#xff0c;每次改动之后&#xff0c;都能自动发现对现有功能的影响。 1 测试要求 在对软件单元进行动态测试之前&#xff0c;应对软件单元的源代码进行静态测试&#xff1b; 应建立测试软件单元的环境&#xff0c;如数据准备、桩模块、模拟器…