counter-reset 和 counter-increment 在媒体查询中不生效,因为css计数器依赖文档流和渲染树,而非运行时变量;媒体查询仅控制样式应用,无法动态重置计数器状态。

为什么 counter-reset 和 counter-increment 在媒体查询里不生效?
直接在 @media 规则里写 counter-reset 或 counter-increment 不会重置或改变计数器状态——CSS 计数器是基于文档流和渲染树的,不是运行时变量。媒体查询只控制样式是否应用,但计数器的初始化和递增必须发生在元素实际渲染的上下文中。
- 正确做法:把
counter-reset放在容器(如<ol></ol>或<section></section>)上,counter-increment放在要编号的子元素(如<h2></h2>、<article></article>)上 - 响应式编号的关键不是“在断点重置计数器”,而是让容器的
counter-reset值随布局变化而重新计算——但 CSS 本身不支持动态值;所以通常用 JS 控制,或改用语义化<ol></ol> - 若强行用媒体查询干预,只能通过切换不同
counter-reset的 class 来模拟,例如:.list--reset-sm { counter-reset: section 0; }配合 JS 切换 class
用 <ol></ol> 替代自定义计数器更可靠吗?
是的,尤其在响应式场景下。<ol></ol> 原生支持 start、reversed、type,且浏览器自动维护序号逻辑,不受 flex/grid 折行、display: none 或媒体查询隐藏的影响。
-
<ol start="3"></ol>可从任意数字开始,比counter-increment: section 2更直观 - 配合
ol { counter-reset: none; }可禁用默认计数器,再用::marker自定义样式(现代浏览器支持) - 注意:IE 不支持
::marker,若需兼容,仍得回退到counter-increment + ::before - 当列表项被
flex-wrap: wrap拆成多行时,<ol></ol>的序号依然连续;而手动用counter-increment的<div> 若被 JS 动态插入/移除,极易错位 <h3> <code>::before中counter()函数的常见错位原因最常出现“编号重复”“跳号”“全显示 0”的情况,基本都源于计数器作用域混乱或伪元素未正确绑定。
- 忘记给父容器设
counter-reset:没有重置就没有初始值,counter(section)默认返回 0 - 在浮动或绝对定位元素上用
counter-increment:它们脱离文档流,可能被浏览器跳过计数(尤其旧版 Safari) - 用
display: contents包裹编号项:该声明会让父元素“消失”于格式化上下文中,导致counter-reset失效 - 多个同名计数器嵌套时未指定 scope:例如外层
counter-reset: item,内层又写counter-reset: item,会覆盖而非继承;应改用counter-reset: item 0显式重置
移动端适配时,如何避免编号被截断或挤压?
编号本身不占内容流空间,但
::before生成的内容若用position: absolute或固定宽度,容易在小屏上溢出或遮挡文字。- 优先用
display: inline-flex+gap控制编号与内容间距,避免硬编码width或margin-left - 编号文字用
font-size: clamp(0.875rem, 4vw, 1rem),确保小屏可读、大屏不撑开 - 若编号需右对齐(如侧边栏目录),别用
text-align: right,而用grid-template-columns: auto 1fr分离编号区和内容区 - 测试真机:iOS Safari 对
counter()的字体抗锯齿处理较弱,字号小于 14px 时易模糊,建议最小设为0.875rem(14px)
counter-reset: step,又在某个组件里也用step,结果整个页面编号串了。命名加前缀(如faq-step、tutorial-step)比省事更重要。 - 忘记给父容器设











