纯 CSS 实现标签自动显示超出数量

2024-05-10 22:36

本文主要是介绍纯 CSS 实现标签自动显示超出数量,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

这次我们来用 CSS 实现这样一个功能:有多个宽度不同的标签水平排列,当外层宽度不足时,会提示超出的数量,演示效果如下

Kapture 2024-04-01 at 00.28.32

如果让我用 JavaScript来实现估计都有点折腾,毕竟宽度都是动态的,要监听各部分的尺寸变化,包括标签的位置和外层的宽度,总之不是一两行代码就能搞定的。

现如今,纯CSS也能完美的实现这样的效果,而且比 JS 实现更加简单,一起来看看吧

一、CSS 实现思路

很多时候,CSS并没有直接的实现方式,需要“绕”点弯路,将需求拆分成很多小点,然后逐一突破。

回到本文这里,其实有几个问题需要考虑:

  1. CSS 如何动态累计数字?
  2. CSS 如何知道哪些元素在容器之外?
  3. CSS 如何区分是否溢出(显示数量)

关于第3点,其实在之前这篇文章中有详细介绍,有兴趣可以回顾一下,非常有意思

纯 CSS 检测文本是否溢出

那么第一点,CSS有没有什么方式可以统计数量呢?

没错,相信很多小伙伴已经猜到了,就是利用 CSS计数器,示意如下

counter-reset: num var(--num);
counter-increment: num;
::after{content: "+"counter(num);
}

关于计数器,我之前也在很多文章中有用到

你可能不需要 JS!CSS实现一个计时器

如何让CSS计数器支持小数的动态变化?

还在使用定时器吗?CSS 也能实现电子时钟

动画合成小技巧!CSS 实现动感的倒计时效果

自定义计数器小技巧!CSS 实现长按点赞累积动画

然后是第二点,CSS有什么方式可以知道元素是出去了还是在视野之内呢?

如果是用 JS来判断的话,最稳妥的方式应该Intersection Observer(交叉观察者),相信很多同学都用过,这个在图片懒加载非常有用

交叉观察器 API - Web API 接口参考 | MDN (mozilla.org)')

那么,CSS中有什么类似的呢?没错,还是之前提到过的CSS滚动驱动动画。

不过这里用到的是视图进度,也就是关注的是元素自身位置,元素进入到容器范围之内就会触发动画,非常类似 JS中的Intersection Observer

tag{animation: appear;animation-timeline: view(inline);animation-range: contain;
}
@keyframes appear{to {background-color: #9747FF;}
}

这里就不详细介绍了,有兴趣回顾之前这篇文章

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

好了,关键原理就这些了,我们需要做的就是想办法将计数器元素进出容器范围关联起来就行了,接着往下看

二、CSS 计数器

利用 CSS 计数器,我们可以很轻松的统计元素的数量。

先简单布局一下文章开头的例子,HTML如下所示

<div class="con"><a class="tag">HTML</a><a class="tag">CSS</a><a class="tag">JavaScript</a><a class="tag">Flutter</a><a class="tag">Vue</a><a class="tag">React</a><a class="tag">Svelte</a>
</div>
<span class="num"></span><!--用来计数的标签-->

然后美化一下

.con{display: flex;gap: 5px;padding: 5px;overflow: hidden;
}
.tag{padding: .2em .5em;background-color: #c49ef5;color: #fff;border-radius: 4px;animation: appear;
}
.num::after{content: "+0";padding: .2em .5em;background-color: #FFE8A3;color: #191919;border-radius: 4px;
}

这样就得到了水平排列的 tag 布局(超出隐藏),后面跟一个数字

image-20240331230107248

现在我们定义一个计数器,然后通过每个tag进行累计,有多个tag相当于多少次累加,最后在::after中显示出来

.con{counter-reset: num;  /*计数器初始值,默认为0*/
}
.tag{counter-increment: num; /*计数器增量值,默认为1*/
}
.num::after{content: "+"counter(num); 
}

默认计数器的起始值是 0,每次累计是1,所以这里最后得到了7,这样就能实时统计元素的数量了

image-20240331224729698

当然,我们也可以自定义这些默认值,比如

.con{counter-reset: num 10;
}
.tag{counter-increment: num -1;
}

这种情况下,起始值是10,增量值是-1,所以最后得到了3,如下

image-20240331225201053

那么,该如何统计容器之外的标签数量呢?

三、CSS 滚动驱动动画

这里我们要利用CSS 视图进度时间轴,也就是观察元素自身的位置,在进入到容器范围之内执行动画。

拿上面这个例子,我们给标签添加一个动画,让标签在进入到容器之内时变个颜色,实现如下

.tag{animation: appear;animation-timeline: view(inline);
}
@keyframes appear{to {background-color: #4d47ff;}
}

由于是水平方向,所以这里需要设置view(inline) ,效果如下

Kapture 2024-03-31 at 23.15.42

好像不是很明显?这是因为动画是在整个视区内过渡的,我们可以改变动画时间线的区间animation-range,让这个动画在进出的一瞬间就变化

.tag{animation: appear;animation-timeline: view(inline);animation-range: contain;
}
@keyframes appear{from,to {background-color: #4d47ff;}
}

效果如下

Kapture 2024-03-31 at 23.10.18

那么,这个效果和前面的计数器有什么关联呢?

从效果上来看,在视区内会执行一个动画,如果在这个动画中加入计数器的累加会怎么样呢?先去除原先的累加器

.tag{/* counter-increment: num; */
}
@keyframes appear{from,to {background-color: #4d47ff;counter-increment: num;}
}

可以看到计数器已经生效了,不过现在统计的在可视区内标签的数量。而我们要统计的是可视区外的数量,好像反过来了,如何实现呢?

这里有两种思路。

第一种,用总数减去可视区内的数量,不就行了吗?由于现在动画是针对可视区内的,我们可以给计数器设置一个初始值,就是总量,然后动画中给累加值设置为-1,就相当于减去当前数量了,实现如下

.con{counter-reset: num 7;
}
@keyframes appear{from,to {background-color: #4d47ff;counter-increment: num -1;}
}

这样就完美统计出了可视区外的数量了

Kapture 2024-03-31 at 23.29.34

还有一种方式,我觉得更加巧妙,需要反向思考。原理是重置当前的累加值,比如默认情况下,正常累加,进入可视范围,把累加值设置为0,不就相当于可视区外的正常累加了吗?

.tag{counter-increment: num;
}
@keyframes appear{from,to {background-color: #4d47ff;counter-increment: num 0;}
}

同样能达到相同的效果

Kapture 2024-03-31 at 23.29.34

现在基本已经达到我们需要的效果了

四、其他细节修正

首先是,在超出范围时,需要在边缘出添加一个半透明蒙层,这样体验效果会更好。

半透明蒙层很好实现,只需要添加一个水平渐变的mask遮罩就行了

.con{-webkit-mask: linear-gradient(to right, #fff calc(100% - 30px), transparent);
}

效果如下

image-20240401000026196

那么,如何在没有超出时,不出现这个遮罩呢?

这个其实在之前的文章中有详细介绍了,建议回顾一下

纯 CSS 检测文本是否溢出

利用CSS滚动驱动动画,可以检测容器是否可滚动,也就是是否超出。所以我们只需要将遮罩放在滚动驱动动画里就行了,关键实现如下

.con{animation: check;animation-timeline: scroll(x self);
}
@keyframes check{from,to {-webkit-mask: linear-gradient(to right, #fff calc(100% - 30px), transparent);}
}

还有一个问题,希望在没有超出的时候不显示后面的数量。

关于这个,我本来是打算用样式查询来实现,但是遇到了一个问题,由于样式查询只能匹配到子元素,所以不得不将显示数量的标签放到.con容器内。但是这样一来,mask遮罩就会出现问题,就像这样

image-20240401001744106

遮罩层连同数量标签一起被裁剪了!

于是又想出了另一种方案,这个在以前的布局中其实用到的更多,那就是负margin

实现很简单,给标签容器一个的负margin-right,这样,右边的数量就会被左边的标签盖住,比如

.con{margin-right: -20px;
}

效果如下

image-20240401002205665

是不是已经被盖住一部分了?我们继续向左偏移

.con{margin-right: -50px;
}

这样就完全看不到右边的数量了

image-20240401002336788

那么,如何在超出时显示数量呢?这里就体现出负margin的好处了,可以借助前一个元素来隐藏后一个元素,在这里,我们直接在前面的动画中还原margin就行了

.con{animation: check;animation-timeline: scroll(x self);
}
@keyframes check{from,to {-webkit-mask: linear-gradient(to right, #fff calc(100% - 30px), transparent);margin-right: 0;}
}

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

前端的世界总是在不断变化,作为开发者,我们需要保持好奇心和学习热情,不断探索新的技术,只有这样,我们才能在这个快速发展的时代中立于不败之地。低代码也是一个值得我们深入探索的领域,让我们拭目以待,它将给前端世界带来怎样的变革。

介绍一款程序员都应该知道的软件JNPF快速开发平台,很多人都尝试用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。

JNPF可以实现应用从创建、配置、开发、测试到发布、运维、升级等完整生命周期的管理。减少了传统应用程序的代码编写量,通过图形化、可视化的界面,以拖放组件的方式,即可快速生成应用程序的产品,大幅降低了开发企业管理类软件的难度。

希望这篇文章对你有所帮助~

这篇关于纯 CSS 实现标签自动显示超出数量的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/977747

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo