要点只有一条:伪元素的内容对辅助技术不可靠、对搜索与复制不可用。所以只放装饰(图标、线条、序号),不要放真实信息。现代浏览器会按 alt 般的规则处理 content 文本,但把它当「可见但不可选」的文字最安全。
::before 加前缀图标 ::before 绝对定位画一条竖线,比 border-left 更可控(能设高度与圆角)
.quote { position: relative; padding-left: 14px; }
.quote::before { content: ""; position: absolute; left: 0; top: .2em; bottom: .2em; width: 3px; background: #0969da; }
单个冒号 :before 与双冒号 ::before 都能工作;规范用双冒号区分「伪元素」与「伪类」(单冒号)。
content 的取值形态字符串拼接 attr() 读属性 未标注时的回退 url() 图片 open-quote / close-quote
.x::before { content: "文字"; } /* 字符串 */
.x::before { content: attr(data-icon) " "; } /* 属性值,可拼接 */
.x::after { content: "(来源:" attr(data-src, "未标注") ")"; } /* attr() 有第二个参数=回退值 */
.x::after { content: url(arrow.svg); } /* 图片 */
.x::before { content: counter(n) "." counter(m); } /* 计数器 */
.x::before { content: open-quote; } /* 引号:跟随 lang 与 quotes 属性 */
.x::before { content: "\201C 前引号可以用 Unicode 转义"; } /* 数字后要有空格分隔 */
.x::before { content: none; } /* 不生成盒子;content: "" 生成空盒子 */
/* 关键:::before/::after 只有在 content 被声明(哪怕是 "")时才会存在 */
counter():给章节做自动编号第一节标题
小节一行,编号是「章.节」拼出来的
另一小节
第二节标题,末尾的引用会带上当前计数值
body { counter-reset: sect sub; } /* 声明计数器(初值 0) */
.sect { counter-increment: sect; } /* 递增 */
.sect::before { content: "第 " counter(sect) " 节:"; }
.sub { counter-increment: sub; }
.sub::before { content: counter(sect) "." counter(sub); } /* 拼两级编号 */
/* 嵌套计数器:counter-reset 写在父级上就会自动嵌套,同一名字在子树里重新起算
样式可选:counter(x, upper-roman) / lower-alpha / cjk-decimal / decimal-leading-zero */
有序列表 <ol start> 与 list-style 已够用;counter() 的价值在「多级编号 + 非列表元素 + 跨元素拼字符串」这类真实需求(论文式标题、题目序号)。
::first-line 让这一整行变粗,字号与宽度决定「第一行」的内容。::first-letter 让首字变大变红,杂志风就靠这两个。
::marker 开放少量属性(content、color、font-*)选中这段文字试试:::selection 改了高亮底色。别用低对比配色,那是可访问性缺陷。
::selection { background: #bff5d1; color: #0a3d1f; }
/* 只允许 color / background / text-shadow / decoration 等少数属性 */
counter + display: inline-grid 居中)右上角红点 悬停:下划线从左展开 外链尾标
尖角 tooltip(border 三角形)
/* 骨架屏:一条 background-position 动画,不需要图片 */
.skeleton { background: linear-gradient(90deg, #eaeef2 0 25%, #f6f8fa 37%, #eaeef2 63%) 0 0/400% 100%;
animation: sk 1.4s ease infinite; }
/* 尖角:零尺寸盒子 + 四条透明 border,只给一侧上色 */
.tip::after { content: ""; border: 6px solid transparent; border-top-color: #24292f; position: absolute; top: 100%; }
/* hover 下划线:动 ::after 的 scaleX,不动 text-decoration(后者不能平滑) */
.ul-anim::after { transform: scaleX(0); transform-origin: left; transition: transform .22s; }
.ul-anim:hover::after { transform: scaleX(1); }
| 限制 | 说明与对策 |
|---|---|
| 不能嵌 HTML | content 里写 <b> 只会显示字面量。需要结构就写进 DOM。 |
| 不可选中、不可搜索、复制丢失 | 所以「必需信息」不要只存在于伪元素里(例如价格、状态文字)。读屏支持参差不齐。 |
| 每个元素只有两个 | 需要三层装饰时:给父用 ::before、子元素用 ::after,或改用真实 <span>、多重 box-shadow、多层 background(第八章)。 |
content 与 alt 的取舍:图片的说明文字属于 HTML(alt),因为它是内容;图标字体/装饰符号属于 CSS,因为它是表现。