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

news2024/12/24 9:46:40

现代 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.coloradmin.cn/o/1660871.html

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

相关文章

【vulhub靶场】Apache 中间件漏洞复现

【vulhub靶场】Apache 中间件漏洞复现 一、Apache HTTPD 换行解析漏洞&#xff08;CVE-2017-15715&#xff09;1. 漏洞详情2. 影响版本3. 漏洞复现 二、Apache多后缀解析漏洞&#xff08;apache_parsing_vulnerability&#xff09;1. 漏洞详情2. 漏洞复现 三、Apache HTTP Serv…

【CCF-CSP】202403-3 化学方程式配平

输入格式&#xff1a; 从标准输入读入数据。 输入的第一行包含一个正整数 n&#xff0c;表示需要判断的化学方程式的个数。 接下来的 n 行&#xff0c;每行描述了一个需要被配平的化学方程式。包含空格分隔的一个正整数和全部涉及物质的化学式。其中&#xff0c;正整数 m 表…

驱动开发-字符设备驱动的注册与注销

1.注册字符设备驱动 #include<fs.h> int register_chrdev(unsigned int major,const char *name,const struct file_operations *fops) 函数功能&#xff1a;注册字符设备驱动 参数&#xff1a;major&#xff1a;主设备号 major>0:静态指定主设备号&#xff0c;不…

创新指南|将会话式AI聊天机器人纳入PLG增长战略

想象一个繁荣的数字城市广场&#xff0c;志同道合的人们在这里分享他们的激情、经验和知识。想象一个将房东与旅行者、顾客与司机、人们与他们喜爱的品牌无缝连接起来的平台。在这个世界里&#xff0c;用户交流促进增长&#xff0c;社区成为推动力。 如果您的应用程序天生不符…

win10无法被远程桌面连接,Win10系统无法被远程桌面连接的原因有哪些

win10无法被远程桌面连接&#xff0c;Win10系统无法被远程桌面连接的原因有哪些&#xff1f; 先&#xff0c;我们需要明确Win10系统无法被远程桌面连接的可能原因。其中&#xff0c;最常见的原因包括&#xff1a;远程桌面功能未启用、网络连接问题、防火墙或安全软件设置不当、…

kubernetes删除命名空间下所有资源

kubernetes强制删除命名空间下所有资源 在 Kubernetes 中&#xff0c;当一个命名空间处于 Terminating 状态但不会完成删除过程时&#xff0c;通常是因为内部资源没有被正确清理。要强制删除这个命名空间及其所有资源&#xff0c;你可以采取以下步骤&#xff1a; 1. 确认命名空…

Rocketmq如何保证消息不丢失和幂等性

生产者 生产者通过RocketMQ提供的事务消息&#xff08;两阶段提交&#xff09;能保证消息的一致性。 第一阶段给Broker发送一个半事务消息&#xff0c;半事务消息是不能消费的消息&#xff0c;broker已经收到生产者发送的消息&#xff0c;但是并未收到生产者的二次确认&#x…

网络编程--tcp三次握手四次挥手

1、三次握手 &#xff08;1&#xff09;三次握手的详述 首先Client端发送连接请求报文&#xff0c;Server段接受连接后回复ACK报文&#xff0c;并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文&#xff0c;并分配资源&#xff0c;这样TCP连接就建立了。…

【计算机毕业设计】springboot果蔬种植销售一体化服务平台

伴随着我国社会的发展&#xff0c;人民生活质量日益提高。于是对果蔬种植销售一体化服务管理进行规范而严格是十分有必要的&#xff0c;所以许许多多的 信息管理系统应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套果蔬种植销售一体化服务平台&…

【LLM 论文】Chain-of-Verification:通过验证链来减少 LLM 幻觉

论文&#xff1a;Chain-of-Verification Reduces Hallucination in Large Language Models ⭐⭐⭐ arXiv:2309.11495 论文速读 LLM 由于不可避免地会产生幻觉&#xff0c;现有的研究主要鼓励 LLM 在产生 response 之前生成内部思想的推理链&#xff0c;或者通过 self-critique…

FreeRTOS任务调度器

目录 1、什么是任务调度器 2、FreeRTOS中的任务调度器 2.1 抢占式调度 2.2 时间片调度 2.3 协作式调度 3、任务调度案例分析 3.1 实验需求 3.2 CubeMX配置 3.3 代码实现 3.3.1 uart.c 重定向printf 3.3.2 打开freertos.c并添加代码 3.3.4 代码现象 1、什么是任务调度…

苹果电脑免费第三方软件CleanMyMac X2025电脑版垃圾清理软件神器

Mac电脑用户在长时间使用电脑之后&#xff0c;时常会看到“暂存盘已满”的提示&#xff0c;这无疑会给后续的电脑使用带来烦恼&#xff0c;那么苹果电脑暂存盘已满怎么清理呢&#xff0c;下面将给大家带来一些干货帮你更好地解决这个问题。 CleanMyMac X2024全新版下载如下: h…

【C++】list的使用与模拟实现

&#x1f525;个人主页&#xff1a;北辰水墨 &#x1f525;专栏&#xff1a;C学习仓 本节内容我们来讲解list的使用和模拟实现。 本节难点&#xff1a;list迭代器的模拟实现。 一、list的介绍&#xff1a; 列表 列表是一种序列容器&#xff0c;允许在序列的任何位置进行时间复…

winform植物大战僵尸

winform植物大战僵尸 植物大战僵尸源码 半成品 需要的拿去学习 登陆注册选择关卡 向日葵 豌豆射手 双枪豌豆射手 项目获取&#xff1a; 项目获取&#xff1a;typora: typora/img (gitee.com) 备用项目获取链接1&#xff1a;yifeiyixiang/kamo: 源码下载 (github.com) 备用…

Python图形复刻——绘制母亲节花束

各位小伙伴&#xff0c;好久不见&#xff0c;今天学习用Python绘制花束。 有一种爱&#xff0c;不求回报&#xff0c;有一种情&#xff0c;无私奉献&#xff0c;这就是母爱。祝天下妈妈节日快乐&#xff0c;幸福永远&#xff01; 图形展示&#xff1a; 代码展示&#xff1a; …

一定行:从零起步进入Java世界

郑重声明&#xff1a;本篇博客唯一目的就是带你从零起步&#xff0c;成功编写并运行你的第一个Java应用。 零&#xff1a;先给祖师爷来上柱香 Java之父简介 英文名&#xff1a;James Gosling中文名&#xff1a;詹姆斯高斯林祖籍&#xff1a;加拿大出生年&#xff1a;1955照片…

INS 论文分享:一种用于交通流预测的多通道时空Transformer模型

本文主要介绍了我们在长期交通流预测方面的最新研究成果&#xff0c;该成果已发表在信息学领域的顶级期刊《Information Sciences》上&#xff0c;论文题目为《A Multi-Channel Spatial-Temporal Transformer Model for Traffic Flow Forecasting》。该论文的第一作者及通讯作者…

Android项目转为鸿蒙,真就这么简单?

最近做了一个有关Android转换成鸿蒙的项目。经不少开发者的反馈&#xff1b;许多公司的业务都增加了鸿蒙板块。 对此想分享一下这个项目转换的流程结构&#xff0c;希望能够给大家在工作中带来一些帮助。转换流程示意图如下&#xff1a; 下面我就给大家介绍&#xff0c;Android…

Android 屏幕适配全攻略(上)-掌握屏幕单位,应对千变万化的设备

本文从 Android 开发中常见的长度单位 px、dp、sp 入手&#xff0c;详细介绍了它们的特点及转换关系。 接着深入探讨了屏幕尺寸、分辨率、像素密度等重要的屏幕指标&#xff0c;帮助读者全面理解它们之间的联系。最后&#xff0c;通过实例代码演示了如何在代码中进行单位转换&…

UE4\UE5 调试源代码流程(重点讲不去Github装源代码情况)

UE4\UE5 调试源代码流程 前言&#xff1a; 很多写UE C代码的小伙伴&#xff0c;肯定发现了&#xff0c;在虚幻源代码里面是没办法打断点进行调试的&#xff0c;就算走Debug调试流程&#xff0c;也依旧不能正常打断点调试&#xff0c;今天我们来分享一下不装Github源代码情况下…