写这篇文章是因为,昨天在组里临时做了个分享,觉得还蛮有意思的,所以想记录下来。分享内容是讲 CSS Counter 的,从怎么使用它,到它的实际使用价值,以及一些延伸的用法。那我们直接进入正题。

怎么使用 CSS Counter

首先要明确的是,CSS Counter 从一开始就是为了解决列表项的序号展示需求而设计的。功能上,它能够用来统计元素的个数,并通过赋给 CSS 的 content 属性来展示在页面上。

那么,如果让你设计一个计数器,你会怎么设计呢?我觉得应该至少包含这几个部分: 1. 计数目标:你要统计什么 2. 计数增量:目标没出现一次,加多少 3. 清零:重置计数值 4. 计数值:当前出现的目标数量 * 计数增量

所以用 JS 代码可以这样写:

class Counter {count = 0 // 计数值constructor(target, increment) {// 计数算法if (appear(target)) {count += increment}}// 清零reset() {this.count = 0}
}

换成 CSS 的话,我们首先需要创建一个 Counter:

.reset {counter-reset: test;
}

“test” 表示计数器的标识。有人会疑问counter-reset不是代表重置的意思吗?对,它确实是重置计数器值的意思,但同时也起了创建一个计数器的作用。所以这行代码的完整意思是:创建一个计数器,它的标识是 “test”,并且在遇到 .reset 元素时,重置计数值。

接下来需要指定计数对象和每次计数的增量。同样的,CSS 在设计上将这两个功能合并成了一个属性。因为是为了统计“元素”的个数,所以在 CSS 中,计数目标是代表某个元素的选择器,比如:

.target {}

然后可以通过设置 counter-increment 属性来表示,计数器 test 每遇到一个 .target 元素就加1:

.target {// 第二个参数可以省略,默认为 1。counter-increment: test 1;
}

在 js 中,我们通过 counter.count 来获得计数值。而在 css 中,我们可以通过 counter() 方法来获取,并赋给 content 属性就可以在节点中展示出来了:

.count:before {content: counter(test);
}

另外还可以通过 counters 方法,获得嵌套的计数器的计数拼接值。这里的嵌套关系来源于元素的父子关系,如果两个设置了计数器的元素是父子关系,那么这两个计数器就是嵌套关系。代码示例:

.count:before {// 嵌套值会展示成这样的格式 "1-2-3"content: counters(test, "-");
}

更多 CSS Counter 的语法和使用方式,可以参考MDN 文档,这里就不再赘述。

CSS Counter 的实用价值

平时如果遇到有序列表的需求,序号都是通过模板硬编码实现的,比如:

<h2>《三十六计》</h2><ol className="category">
{chapters.map((chapter, ci) => (<><li className="title">{String.fromCharCode(97 + ci)}. {chapter.title}{chapter.sections && (<ol className="section">{(chapter.sections || []).map((section, si) => (<li className="title">{String.fromCharCode(97 + ci)}-{String.fromCharCode(97 + si)}. {section.title}</li>))}</ol>)}</li></>
))}</ol>

效果:

这样就可以渲染出一个有序列表。对于类似的列表展示需求,大多数情况我不会想到使用 CSS 来实现,这里主要原因可能是语言上下文的切换成本 > 直接硬编码的成本。但是如果对于一些特殊需求,硬编码的成本 > 语言上下文切换的成本,我们就可以尝试使用 CSS Counter 来实现了。比如产品要求需要不再是“a, b, c, d…”而是 “壹,贰,叁,厮...”,这时候我们可能需要实现一个中文计数序号编码算法。可能有些同学说实现一个也不是很难啊?是的,但这取决于开发的知识储备,如果之前没有实现过的,成本肯定是大于直接使用 CSS 来实现的。使用 CSS,我们只需要设置一下counter 或 counters 的最后一个参数即可:

counter(test, 'simp-chinese-formal')

另外 CSS 还实现了非常多其他的序号样式,可以参考:list-style-type - CSS(层叠样式表) | MDN 比起实现计数序号编码算法,CSS 只用加个参数,显然要简单很多。 浏览器兼容性可参考:list-style-type - CSS(层叠样式表) | MDN 可以看到,很多都是可以在大多数生产环境中被使用了。所以,如果产品需求中出现了多种编码方式的序号,就可以考虑使用 CSS Counter 来实现。

下面再来看下另外一个功能需求 — 内容防复制。

如上图所示,我们在选择列表的时候,可以发现,序号是没有被选上的。并且也无法被复制。之所以有这样的表现,是因为序号的内容是通过 css 的 content 属性来生成的,实际的 DOM 节点的 content 属性中,并没有内容。那么,我们是不是可以通过相同的技术来实现内容防复制功能呢?本质上,我们是利用了 CSS content 属性带来的特性。比如这样写,我们就可以将章节内容“隐藏”起来:

<h2>《三十六计》</h2><ol className="category category--css">
{chapters.map((chapter, ci) => (<><li className="title" data-content={chapter.title}>{chapter.sections && (<ol className="section">{(chapter.sections || []).map((section, si) => (<li className="title" data-content={section.title}></li>))}</ol>)}</li></>
))}</ol>.category--css .title:before {content: counters(test, "-", simp-chinese-formal) ". " attr(data-content);
}

我们再回到内容防复制功能本身,要实现这个功能并不是只有这一种方式,比如通过 -webkit-user-select: none;。虽然这在大多数环境中是有效的,但是在safari 中会遇到一个问题 -- 虽然看起来没被选中,但是确可以被复制。当你选择的区域包含可复制和不可复制的内容,那么在 safari 中,不可复制的区域就会被隐形选中,复制的内容中也会包含不可复制的内容,如图:

所以我们必须将整个页面设置为 -webkit-user-select: none 才可以使得内容不可被复制。相比起来,使用 content 来实现不可复制,是一个兼容性更强的方案。

其实 content 内容生成技术,已经被使用在了很多场景里,比如使用 attr 方法展示图片 hover 提示、字体图标等。网上可以搜到很多资料,这里也不再展开。

总结

最后总结一下,如果产品需求里要求展示多种编码方式的序号,可以考虑使用 CSS Counter 来生成序号;如果想要实现文本不可复制功能,CSS content 生成技术是一个兼容性相对较好的方案。


附完整代码示例:

cranky-chaplygin-fltup - CodeSandbox​codesandbox.io

js table 生成序号_CSS Counter 以及 CSS content 内容生成技术的实用价值相关推荐

  1. :after伪类 content内容生成经典应用举例——张鑫旭

    一.简单说说content内容生成 content内容生成就是通过content属性生成内容,content属性早在CSS2.1的时候就被引入了,可以使用:before以及:after伪元素生成内容. ...

  2. content 内容生成技术2

    计数器效果可是说是content的重中之重, 此功能非常强大.实用, 且不具有可替代性, 甚至可以实现连js都不好实现的效果. 这个地方放慢节奏, 细细品味. 先来个例子体验一下: .reset {c ...

  3. js table 生成序号_el-table树形表格表单验证,js树形列表生成序号

    树形表格表单验证预览 树形列表生成序号 首先需要生成一个序号用来确定表单验证的目标row,通过广度优先遍历,以1,1.1,1.1.1的规则对树形列表生成确定唯一值的索引,因为列表自身可以做CURD,因 ...

  4. js table 生成序号_el-table树形表格表单验证(列表生成序号)

    树形表格表单验证预览 树形列表生成序号 首先需要生成一个序号用来确定表单验证的目标row,通过广度优先遍历,以1,1.1,1.1.1的规则对树形列表生成确定唯一值的索引,因为列表自身可以做CURD,因 ...

  5. css使用计数器自动标序号,counter()和counters()的区别及具体用法

    说明:通过css计数器,我们可以只用一个简单的变量,来实现多个列表嵌套的排序输出. 原理:通过css计数器的自加功能实现编号的目的. 用到的属性: content-使用 ::before 和 ::af ...

  6. vue js table colspan rowspan

    需求,要写一个菜单权限表.需要做到单元格合并,本来用的antd-vue的表格,然后构造customRender,总感觉有点本末倒置,其实自己实现,更快,而且想改哪里,改哪里.下面是写这个功能前的测试d ...

  7. CSS 框的生成:块级元素和块框

    在盒模型中,一切皆为框,即页面上的每个元素会生成一个矩形框.默认情况下,一个元素的类型,决定了该元素生成框的类型.块级元素生成块级框,行内级元素生成行内级框,没有被任何元素所包含的文本生成匿名框. 也 ...

  8. HTML+CSS+JavaScript 迷宫生成算法 【建议收藏】

    最近发现很多人都在写算法类的博客,今天就献丑了使用HTML,CSS和JavaScript制作一个简单的迷宫生成小代码.证明了自己对一些简单的小算法还是可以驾驭的,基本功没有荒废. 迷宫生成有很多种算法 ...

  9. 使用前端QrCode.js实现根据输入内容生成二维码,并提供二维码下载功能(已使用在交付项目中)

    前端QrCode 根据输入内容生成二维码,并提供二维码下载功能 简介:这是一个使用前端QrCode自动生成二维码并下载二维码图片的项目. 项目背景:在某个项目的交付阶段,客户提出需要一个可手动生成二维 ...

最新文章

  1. 第五周实践项目6 数制转换(栈)
  2. 整合 Google 开源 C++ 代码
  3. 【BZOJ5469】[FJOI2018]领导集团问题(动态规划,线段树合并)
  4. 收银机多少钱一台推荐科脉系统_防火门监控系统安装预算多少钱?防火门监控系统安装预算表[今日推荐]...
  5. Linux + RIL.pdf
  6. 21世纪的设计模式:适配器模式
  7. MySQL 客户端命令
  8. linux回到桌面的命令符_三 基本的base shell 命令
  9. javascript回调函数及推论
  10. 301永久重定向实现方式及302重定向(侧重.htaccess)
  11. MFC无法使用CDialogEx类
  12. 因开源协议“大打出手”,AWS 宣布创建 Elasticsearch、Kibana 分支
  13. 【SpringBoot】SpringBoot最精简的设置
  14. MySQL主从复制延迟原因及处理思路
  15. Luogu P4109 [HEOI2015]定价 贪心
  16. gradle 配置及设置本地仓库
  17. android 高德地图 java.lang.UnsatisfiedLinkError: Native method not found: com.autonavi.amap.mapcore.MapC
  18. 官网下载storage manager方法
  19. 实验七 构件图和部署图
  20. pic系列单片机c语言编程与应用实例,PIC单片机C语言编程实例

热门文章

  1. MYSQL基础八--子查询和连接
  2. 使用EF框架的增删改查和分页的公共类
  3. select框的text与value值的获取(实用版)
  4. css border画图
  5. UVA11888 Abnormal 89‘s【回文】
  6. UVA10341 Solve It【二分】
  7. JSK-129 判断日期是否符合格式【入门】
  8. java 语法 —— final
  9. 半文不白的语言(语气助词)
  10. 实用的摩斯编码(二)