应使用语义化 html 结构:原价用 ¥199,折后价用 ¥159,折扣信息放 8折,整体包裹于 中,确保 js 可读、css 可控、屏幕阅读器可识别。

怎么用 HTML 搭出原价和折后价的对比结构
纯 HTML 本身不计算折扣,它只负责把“原价”“折扣率”“折后价”这些字段按逻辑关系组织起来。真正算数得靠 JavaScript,但结构设计直接影响后续 JS 是否好写、样式是否好对齐、屏幕阅读器是否能正确识别。
常见错误是直接写 <div>¥199</div>
<div>¥159</div>,既没语义也没关联性,JS 拿不到哪个是原价、哪个是折后,CSS 也难统一控制删除线或颜色。
- 用
<del></del>包原价(语义明确表示“被删减的价格”,屏幕阅读器会读作“删除线 ¥199”) - 折后价用
<span class="price-sale"></span>或类似类名,避免用<b></b>/<strong></strong>单纯强调视觉 - 把折扣信息(如“8折”“立减40元”)单独放在
<span class="discount-label"></span>里,别塞进价格数字中 - 整个结构建议包裹在
<div class="price-group"> 下,方便后续 JS 批量查找或 Vue/React 绑定<h3>为什么不能只靠 CSS 实现动态折扣计算</h3> <p>CSS 可以用 <code>attr()读取元素属性值,比如content: attr(data-original);,但它不能做四则运算、不支持小数点处理、无法响应用户输入变化——也就是说,你改了data-discount="0.8",CSS 不会自动重算data-original="199"× 0.8 的结果。典型翻车场景:想用
calc()做减法,写成width: calc(attr(data-original) * attr(data-rate) * 1px);,结果浏览器直接忽略——attr()在calc()里不被支持,且返回值类型不可控(可能是字符串或空)。- 所有涉及数值运算、条件判断(比如“满300减50”)、实时响应(输入框改折扣率立刻更新)的逻辑,必须交给 JavaScript
- CSS 只管展示:比如用
[data-sale="0"]隐藏折后价,或用.price-group--on-sale .price-original加删除线 - 如果硬要用 CSS 模拟“计算”,只能预设有限几组静态值(如 7 折、8 折、9 折),靠 class 切换,扩展性极差
JavaScript 计算折扣时最常踩的坑
不是算不准,而是“算对了但显示错”或“用户改了输不进去”。核心问题出在数据类型和事件绑定时机上。
- 用户输入的
discountRate是字符串,比如"0.8"或"8",直接* 199会得到"0.8199"(字符串拼接),必须用parseFloat()或一元加号+input.value - HTML 中价格常用
<input type="number">,但它会把空值转成"",而+"" === 0,导致“清空输入框反而显示 ¥0” - 监听
input事件比change更及时,但要注意防抖——用户快速连打 “85” 时,别每按一次都触发完整计算+DOM 更新 - 金额必须保留两位小数,但
toFixed(2)返回字符串,且199.005.toFixed(2) === "199.00"(银行家舍入),如需严格向下取整,得用Math.floor(num * 100) / 100
示例关键片段:
const original = parseFloat(document.querySelector('[data-original]').dataset.original) || 0;<br>const rate = parseFloat(discountInput.value) || 0;<br>const sale = original * (rate saleEl.textContent = '¥' + Math.floor(sale * 100) / 100;移动端输入折扣率时的兼容性注意点
安卓微信内置浏览器、部分国产浏览器对
input type="number"的软键盘支持混乱:可能弹出数字键盘但允许输入字母,或强制补零(输“8”变“08”),导致 JS 解析失败。- 优先用
input type="text" inputmode="decimal"(iOS/Android 较新版本支持),配合pattern="[0-9.]*"和 JS 过滤 - 不要依赖
step="0.1"控制精度,它在很多浏览器里无效,且会干扰非数字输入 - 用户输入 “8.5折”“八五折” 这类中文,前端可正则提取数字,但更稳妥的做法是 UI 上只提供滑块或预设按钮(7折/8折/9折),避开自由输入
- 注意 iOS Safari 对
inputmode="numeric"的兼容性较差,decimal更稳
结构和计算逻辑本身不复杂,难的是在各种输入方式、浏览器差异、无障碍要求之间找平衡点——尤其当产品要同时支持 PC 后台录入和手机端用户自调折扣时,DOM 结构得预留足够语义和钩子,别等 JS 写完了才发现原价节点找不到父容器。











