商品卡片应使用语义化HTML结构:用<article>包裹,标题用<h3>,价格等关键字段用带语义类名的标签(如<span class="price">),主图<img>必须含描述性alt属性,促销标签用<span role="note">,按钮统一为<button type="button">;CSS布局优先用flex实现单列流,大屏再切grid,禁用固定高度,图片区域设aspect-ratio: 1/1并object-fit: cover,价格区用display: flex对齐基线,文字行高统一line-height: 1.4,断点仅设768px和1024px;JS更新需局部操作,用textContent、dataset和classList.toggle(),避免innerHTML重绘;移动端按钮设min-height: 44px、touch-action: manipulation,并用伪元素扩展热区;字体宽度适配用ch单位(如max-width: 12ch)确保跨平台一致性。
直接用 <article> 包裹商品信息,比用 <div> 更语义化,搜索引擎和屏幕阅读器都能更好理解这是独立商品单元。标题必须用 <h3>(不是 <h2> 或 <span>),价格、原价、销量这些关键字段要放在有明确含义的标签里,比如价格用 <span class="price">,原价加 aria-hidden="true" 避免读屏重复播报。
常见错误:把整个卡片塞进一个 <div class="card">,里面所有文字都用 <span>,结果爬虫抓不到标题层级,无障碍访问也失效。
<img>,必须带 alt 属性,内容为商品名+核心属性(如“iPhone 15 Pro 钛金属版”)<span role="note">,不干扰主信息流<button type="button">,避免默认提交行为误触发别一上来就写 display: grid —— 在小屏上,flex 的单列流更可控;大屏再切为 grid。重点不是“多好看”,而是“换图/改价/加标签后会不会撑破容器”。
容易踩的坑:给卡片设固定高度(height: 200px),一旦标题变长或促销文案加长,文字直接被裁掉;或者用 font-size: clamp() 却没配 line-height,导致行距错乱。
立即学习“前端免费学习笔记(深入)”;
aspect-ratio: 1 / 1 + object-fit: cover,确保不同尺寸图都居中裁切display: flex + align-items: baseline,让 <del> 原价和当前价基线对齐line-height: 1.4,避免字体缩放时重叠@media (min-width: 768px) 和 @media (min-width: 1024px),够用且易维护用户点击规格切换后,如果直接 innerHTML = newHtml,会丢失已绑定的事件监听器(比如“加入购物车”按钮的点击逻辑),还会清空输入框焦点、滚动位置等状态。
真正该做的是局部更新:只替换价格数字、库存文案、禁用状态,其余结构不动。用 textContent 改文字,用 dataset 控制状态,用 classList.toggle() 切换样式类。
data-price-field 属性,JS 通过 document.querySelector('[data-price-field]') 定位并更新disabled 属性 + aria-disabled="true"
<small class="error">暂无报价</small>,而不是留白getElementById,提前缓存节点引用padding 就能解决的iOS Safari 默认将小于 44px × 44px 的可点击区域放大处理,但这个行为不可靠,尤其在 zoom 缩放后失效。真正有效的是用 min-height + min-width 强制最小尺寸,并配合 touch-action: manipulation 关闭双击缩放。
另一个隐形问题:卡片内多个按钮(如“看详情”“加购”“收藏”)靠得太近,手指误触率高。这时不能只靠视觉间距,得用 margin 留出至少 8px 物理间隔,再用 pointer-events: none 配合伪元素扩展热区。
min-height: 44px,内部文字用 line-height: 44px 垂直居中::after 伪元素,content: '' + position: absolute 扩展点击范围min-height 和 padding,否则视觉跳动明显最常被忽略的其实是字体渲染一致性:Mac 上 system-ui 会走 San Francisco,Windows 上走 Segoe UI,Android 走 Roboto —— 这些字体字宽不同,会导致同样 width: 120px 下,“¥199”在 iPhone 上刚好一行,到安卓机上就换行。解决方案不是锁死字体,而是用 ch 单位限制文字容器宽度,比如 max-width: 12ch,让宽度随字符平均宽度自适应。