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

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

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

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

相关文章

有什么方便实用的黏土特效教程?6个软件教你快速进行特效制作

有什么方便实用的黏土特效教程&#xff1f;6个软件教你快速进行特效制作 作为时尚小达人&#xff0c;你自己是否想要制作出属于自己的黏土特效照片呢&#xff1f;比如下面几种。 看到这些黏土特效软件有没有心动&#xff0c;下面我也为大家详细的介绍一下可以制作出对应特效的…

Java 集合-List

集合主要分为两组(单列集合, 双列集合) Connection 接口有两个重要的子接口LIst 和 Set, 它们的实现子类都是单列集合, Map 接口的实现子类是双列集合, 存放的是 K-V Connection 接口 Collection 接口和常用方法 下面以 ArrayList 演示一下 add: 添加单个元素remove: 删除指…

Socket学习记录

本次学习Socket的编程开发&#xff0c;该技术在一些通讯软件&#xff0c;比如说微信&#xff0c;QQ等有广泛应用。 网络结构 这些都是计算机网络中的内容&#xff0c;我们在这里简单回顾一下&#xff1a; UDP(User Datagram Protocol):用户数据报协议;TCP(Transmission Contr…

这是一关于DSC相关的文档

这是一关于DSC相关的文档 上面这幅图清晰的展示了somewhat flat的像素图示

机器学习算法应用——关联规则分析(4-4)

关联规则分析&#xff08;4-4&#xff09; 关联规则分析&#xff08;Association Rule Mining&#xff09;是一种基于频繁项集的分析方法&#xff0c;它以最常出现在一起的元素之间的关系作为分析对象&#xff0c;主要用于发掘大数据中隐藏的关联规则&#xff0c;是数据挖掘技术…

小众行业风口:Q1季度擦窗机器人行业线上市场销售数据分析

今天给大家分享一个2024年的小众行业增长风口——擦窗机器人。 作为家居自动化里的重要一员&#xff0c;擦窗机器人可以简称为擦窗神器&#xff0c;是为了解决大户型家庭的外窗清洁痛点而存在。而目前&#xff0c;擦窗机器人行业正在走向成熟&#xff0c;且市场需求量居高不下…

苹果公司因iPad广告争议而道歉,承认“未达标”|TodayAI

周二&#xff0c;苹果公司发布了一则新的iPad Pro广告&#xff0c;引起了广泛争议&#xff0c;该公司随后发表道歉声明&#xff0c;承认这则广告“未达标”。这则名为“压碎&#xff01;”的广告意图展示全新的M4芯片iPad Pro的创意潜力&#xff0c;但却因其表现方式而备受批评…

设计模式学习笔记 - 回顾总结:在实际软件开发中常用的设计思想、原则和模式

概述 本章&#xff0c;先来回顾下整个专栏的知识体系&#xff0c;主要包括面向对象、设计原则、编码规范、重构技巧、设计模式五个部分。 面向对象 相对于面向过程、函数式编程&#xff0c;面向对象是现在最主流的编程范式。纯面向过程的编程方法&#xff0c;现在已经不多见了…

浅谈如何利用 AI 提高内容生产效率?|TodayAI

在数字化时代&#xff0c;内容的创建和分发速度变得尤为关键。人工智能&#xff08;AI&#xff09;技术提供了加速这一过程的可能性&#xff0c;不仅提升了生产效率&#xff0c;还改善了内容的质量和受众的接受度。本文深入探讨AI如何在内容生成、分发与推广&#xff0c;以及内…

LangChain连接国内大模型测试|智谱ai、讯飞星火、通义千问

智谱AI 配置参考 https://python.langchain.com/v0.1/docs/integrations/chat/zhipuai/ZHIPUAI_API_KEY从https://open.bigmodel.cn/获取 from langchain_community.chat_models import ChatZhipuAI from langchain_core.messages import AIMessage, HumanMessage, SystemMes…

超越机械抓手:看多指机器人如何灵活运用触觉?

论文标题&#xff1a; Learning Visuotactile Skills with Two Multifingered Hands 论文作者&#xff1a; Toru Lin, Yu Zhang, Qiyang Li, Haozhi Qi, Brent Yi, Sergey Levine, and Jitendra Malik 1. 机器人新挑战&#xff1a;多指手指操作 在自动化和智能化日益普及的…

idea导入jar包、打jar包

一、导入jar包 1.在工程下面新建一个lib目录&#xff0c;将jar包放在lib目录下面 2.按步骤导入jar包 -接下来选择jar包所在的位置进行导入 -下图中标红框位置就是刚刚导入的jar包 二、直接用idea打jar包 -下图中Main Class就是选择程序中的Main函数 -右侧标红框位置表示…

VSCode Python 自动格式化代码(black)不生效

弄了很长时间&#xff0c;各种尝试&#xff0c;就想实现保存后自动格式化代码&#xff0c;用户设置&#xff0c;工作区设置&#xff0c;因为环境较多以为有啥冲突&#xff0c;就是没找到。后来看到一条评论说Python版本低&#xff0c;想到了版本问题。然后就看到以下描述 记录…

Spring如何控制Bean的加载顺序

前言 正常情况下&#xff0c;Spring 容器加载 Bean 的顺序是不确定的&#xff0c;那么我们如果需要按顺序加载 Bean 时应如何操作&#xff1f;本文将详细讲述我们如何才能控制 Bean 的加载顺序。 场景 我创建了 4 个 Class 文件&#xff0c;分别命名为 FirstInitialization Se…

python数据分析——数据的选择和运算

数据的选择和运算 前言一、数据选择NumPy的数据选择一维数组元素提取示例 多维数组行列选择、区域选择示例 花式索引与布尔值索引布尔索引示例一示例二 花式索引示例一示例二 Pandas数据选择Series数据获取DataFrame数据获取列索引取值示例一示例二 取行方式示例loc() 方法示例…

人脸图像生成(DCGAN)

一、理论基础 1.什么是深度卷积对抗网络&#xff08;Deep Convolutional Generative Adversarial Network&#xff0c;&#xff09; 深度卷积对抗网络&#xff08;Deep Convolutional Generative Adversarial Network&#xff0c;DCGAN&#xff09;是一种生成对抗网络&#xf…

网工内推 | 软件测试工程师,有软考中、高级认证优先

01 上海碧蔓智能科技有限公司 招聘岗位&#xff1a;软件测试工程师 职责描述&#xff1a; 1、负责软件产品的测试工作&#xff0c;对测试进度和测试质量负责&#xff1b; 2、参与业务需求、设计方案的讨论&#xff0c;负责编写测试方案、测试计划、测试用例&#xff0c;搭建测…

LMDeploy笔记

随谈模型部署 模型部署包含的内容很多&#xff0c;来聊聊。 访存bottleneck 首先&#xff0c;基于transformer的计算是访存密集型任务。 so? 过去&#xff0c;我们表达模型的性能&#xff0c;通常会用ops&#xff0c;macs这些指标,也计算量来衡量模型的推理时间&#xff…

JSP ssm 智能水表管理myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 JSP ssm 智能水表管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采…

Vue自定义封装音频播放组件(带拖拽进度条)

Vue自定义封装音频播放组件&#xff08;带拖拽进度条&#xff09; 描述 该款自定义组件可作为音频、视频播放的进度条&#xff0c;用于控制音频、视频的播放进度、暂停开始、拖拽进度条拓展性极高。 实现效果 具体效果可以根据自定义内容进行位置调整 项目需求 有播放暂停…