CSS系列——四两拨千斤的Content属性

347 阅读6分钟

写在前面

本文部分知识需要有一定的 CSS3 基础,如果有疑问,建议随时 Google 或者联系本人~

写这边文章的起因是前段时间做了一个需求,要求改变 Ant Design 的 TreeSelect 组件的选中事件,要求是如果选中的是父节点,那么就是展开当前节点的子节点,但不能 执行选中自己的事件,一开始纠结了很久去使用官方文档的事件去各种骚操作,后来突然想到了可以使用 content 属性加定位给干出来这种效果,先看看代码:

.ant-select-tree-switcher {
	position: relative;
}
.ant-select-tree-switcher_open::before, .ant-select-tree-switcher_close::before {
  content: '';
  position: absolute;
  right: -310px;
  top: 0;
  left: 0;
  bottom: 0;
}

写完以后突然想到 content 这个小家伙到底还能做什么,顺道重新了解了一下 content 属性,发现这个小家伙还真的是四两拨千斤,具体如下~

一. 认识

首先来看一下官方对于 content 属性的介绍:

该属性用于定义元素之前或之后放置的生成内容。默认地,这往往是行内内容,不过该内容创建的框类型可以用属性 display 控制。 content 属性与 :before 及 :after 伪元素配合使用,来插入生成内容。

image.png    

是不是第一眼看过去,会感觉这哥们平平无奇,但是(重点来了),经本工具人验证,这哥们可以在 Chrome 浏览器中应用在任何元素后面,而不是仅仅只应用在伪类元素后面,鉴于公司业务目前还是主营 Chrome 浏览器,所以。。。(真香警告⚠️)

二. 使用

2.1 默认属性(String 类型皆可)

首先来看一眼 Ant Design 关于表单必填项的提示吧,如下图: image.png image.png image.png 是不是出人意料?它的名称前面的竟然不是 Icon,就是这么普普通通的一个,而且名称之后的冒号也是相同的用法,我们在之前的文章分享关于 CSS 变量时,使用过该属性,可以在页面中动态的点击展示我们想要的信息。效果和代码如下图:

bodyMousedown.gif

CSS 代码如下:

body:active::after {
  transform: translate(-50%, -100%);
  opacity: 0.5;
  transition: 0s;
  left: -999px;
}
body::after {
  content: 'hi~我是内容';
  position:fixed;
  z-index: 999;
  left: calc(var(--clientx, -999) * 1px);
  top: calc(var(--clienty, -999) * 1px);
  transform: translate(-50%, calc(-100% - 20px));
  opacity: 0;
  transition: transform .3s, opacity .5s;
}

JS 代码如下:

document.addEventListener('mousedown', function (event) {
  var html = document.documentElement;
  // 设置自定义属性值
  html.style.setProperty('--clientx', event.clientX);
  html.style.setProperty('--clienty', event.clientY);
});

2.2 HTML 自定义属性

image.png

 .main label::before {
   content: attr(number) " : ";
}
.main label{
  display: block;
}
<form class="main">
  <label class="item" number="1">我是一号</label>
  <label class="item" number="2">我是二号</label>
  <label class="item" number="3">我是三号</label>
  <label class="item" number="4">我是四号</label>
  <label class="item" number="5">我是五号</label>
</form>

知识点来了,content 属性可以获取到 HTML 的自定义属性中的数据,这样一来,我们就可以通过 HTML 标签的自定义属性,来动态的修改每个元素的数据,达到我们想要的类似有序列表的效果。类似原理的关于数字顺序的需求、关于表单的内容都可以使用这种方式去做到~

2.3 counter 计数器

首先来了解一下这个新的小伙伴,看一下官方解释和浏览器兼容性:

CSS 函数 counter(),返回一个代表计数器的当前值的字符串。它通常和伪元素搭配使用,但是理论上可以在支持值的任何地方使用。 一个计数器本身没有可见的效果,而是通过counter()函数(和counters()函数)返回开发人员定义的字符串(或图像) 从而使计数器拥有很棒的作用。

 /* 简单使用 */
counter(计数器名称);
 /* 更改计数器显示 */
counter(countername, upper-roman)

image.png

只看概念,很多人会没有比较好的体感,但是如果你看过刚才链接的文章,就会发现它的强大之处,话不多说,直接上 demo。

image.png

<div class="main">
  <p>进度1 : </p>
  <div class="item" style="--scale: 80;--background: #52c41a"></div>
  <p>进度2 : </p>
  <div class="item" style="--scale: 60;--background: #1890ff"></div>
  <p>进度3 : </p>
  <div class="item" style="--scale: 40;--background: #faad14"></div>
  <p>进度4 : </p>
  <div class="item" style="--scale: 20;--background: #ff4d4f"></div>
</div>
.main {
  width: 400px;
  border: 1px solid #ccc;
  border-radius: 7px;
  padding: 8px;
  margin: 10px auto;
}

.item {
  height: 20px;
  width: 300px;
  background-color: #eee;
  margin-bottom: 10px;
  border-radius: 20px;
}

.item::before {
  /* 用于将 CSS计数器 重置为制定值 progress代表进度条 */
  counter-reset: progress var(--scale);
  /* 
  \00a0 表示 &nbsp; 
  详情请见: https://css-tricks.com/snippets/html/glyphs/ 
  PS:同样是为了右侧距离,设置一下padding-left试一下?
  */
  content: counter(progress) '%\00a0';
  width: calc(300px * var(--scale) / 100);
  color: #fff;
  background-color: var(--background);
  display: block;
  font-size: 12px;
  border-radius: 20px;
  height: 20px;
  line-height: 20px;
  text-align: right;
  overflow: hidden;
}

当然了,要实现这个需求不仅仅需要 counter 和 content 这兄弟俩,还需要使用到 CSS 变量,墙裂建议去看一下之前的文章,对于计数器会有一个更佳的体感。counter 仅仅使用单一属性就可以做到这种效果,但是这个小伙伴还有个强大的地方在于它不止可以接受一个属性,可以接受多个,继续看下去~

  div {
    counter-reset: one 1 two 2 three 3;
  }
  div:before {
    content: counter(one) "/" counter(two) "/" counter(three);
  }
 <div></div>

image.png

顾名思义,计数器,所以 counter 方法中接受的参数只能是数字,例如上面的代码,当数字 1 变为字符串"1"时,页面上的效果就会展示为 0/0/0,因为它的默认数据就是 0,同样的,我们一开始做的利用自定义属性做的有序列表,也可以使用该属性做到,代码如下:

.main{
  counter-reset: counter;
}
.main .item::before {
  counter-increment: counter;
  content: counter(counter) " : ";
}
.main .item{
  display: block;
}
 <form class="main">
   <label class="item">我是一号</label>
   <label class="item">我是二号</label>
   <label class="item">我是三号</label>
   <label class="item">我是四号</label>
   <label class="item">我是五号</label>
</form>

image.png

作为程序猿和游戏宅男,肯定要奔着搞事情的思想继续使劲磨砺 counter 小伙伴,官方介绍里面有这么一句话:

/* 更改计数器显示 */ counter(countername, upper-roman)

后面这个参数我们目前还没有使用道,继续搞起~ image.png

这个小伙伴的第二个属性,目前可以支持的包括 disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | none | inherit,我们继续把刚才的有序列表再美化美化,效果如下:

image.png

在此仅展示 CSS 代码:

 .main{
   counter-reset: counter;
}
.main .item::before {
  counter-increment: counter;
  content: counter(counter, upper-latin) " : ";
}
.main .item{
  display: block;
}

再换一个~ image.png

.main{
  counter-reset: counter;
}
.main .item::before {
  counter-increment: counter;
  content: counter(counter, georgian) " : ";
}
.main .item{
  display: block;
}

emmm,差不多了,不玩了,它毕竟还是个孩子🐶~ 有兴趣的小伙伴可以挨个尝试一下,扩宽自己的知识的广度,万一以后用到了呢?😊

三. 总结

看了这么久,应该对 content 这个小伙伴有一个大致的体感了,其实我们在产品迭代过程中,牵扯到一些常规化的需求时,不妨尝试一下这些比较有趣的操作,可以大大的提升我们做产品迭代的乐趣,鉴于本人目前了解的范围还比较有限,有任何问题或者想法欢迎随时沟通和评论呀~