推荐用内联SVG画打钩图标,因其矢量缩放无损、颜色和动画控制精准、兼容性好且无字体加载延迟问题。

HTML里怎么用纯CSS画个打钩图标
直接用 ✓ 字符最省事,但缩放或换字体时容易变形;想精确控制形状和颜色,得用 SVG 或伪元素。前者兼容性好、可交互性强,后者代码少但修改起来容易漏掉 ::before 的 content 属性。
- 推荐用内联 SVG:
<svg viewbox="0 0 24 24" width="20" height="20"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" fill="green"></path></svg>,viewBox保证缩放不失真,fill可直接改颜色 - 别用 Unicode 字符硬塞进按钮里——比如
<button>✓ 完成</button>,iOS Safari 会把✓渲染得又粗又糊 - 用伪元素实现时,必须给父元素设
position: relative,否则::after会脱标定位
用CSS做简单进度条要注意哪些坑
原生 <progress></progress> 标签语义清晰,但样式定制极难,各浏览器默认外观差异大;手写 div + CSS 更可控,但得自己管好 ARIA 属性,不然屏幕阅读器读不出进度。
-
<progress value="75" max="100"></progress>在 Firefox 里圆角是内置的,Chrome 需要progress::-webkit-progress-bar单独设 - 手写进度条务必加
role="progressbar"和aria-valuenow/aria-valuemin/aria-valuemax,否则无障碍支持直接归零 - 百分比宽度别直接写死在 HTML 里(如
<div class="bar" style="width: 75%">),应该用 JS 动态更新 <code>style.width或切换 CSS 类,方便后续加动画章节完成状态该存在哪里:DOM 还是 JS 状态
如果只是静态页面,用
data-completed="true"这类自定义属性够用;一旦涉及用户操作(比如点击标记完成)、跨设备同步或需要持久化,就得靠 JS 管理状态,DOM 只负责渲染结果。- 纯展示型课程页:给每个章节容器加
data-status="done",CSS 用[data-status="done"] .icon::before显示对勾 - 带交互的在线学习平台:状态存在
localStorage或 Vuex/Pinia 里,DOM 只通过 class(如chapter--completed)反映当前值 - 千万别把完成状态只存 DOM 里又不监听变化——用户刷新页面后,所有“已完成”都会消失
SVG打钩图标比CSS绘制更靠谱的原因
CSS 用
border或transform拼对勾,看着简洁,实际在高 DPI 屏幕或缩放 125% 时容易出现 1px 锯齿;SVG 是矢量,缩放无损,还能直接上渐变、阴影、hover 动画。- 用 CSS 画对勾常见写法:
.check::after { content: ""; display: block; width: 8px; height: 14px; border-right: 2px solid #28a745; border-bottom: 2px solid #28a745; transform: rotate(45deg); }—— 但旋转后边缘发虚,尤其在 Chrome 上 - SVG 里改颜色只要动
fill,加动画只要给<path></path>加transition,不用操心伪元素的渲染上下文 - 如果项目已用 iconfont,注意 WebKit 内核下
@font-face加载延迟可能导致图标闪一下才出现,SVG 内联没这问题
真正麻烦的不是画个对勾或进度条,而是状态同步时机——用户点完“完成”,JS 更新了数据,但 DOM 没立刻重绘,或者 localStorage 写入失败却没降级处理,这种地方一漏,整个完成状态就不可信了。
- 纯展示型课程页:给每个章节容器加











