写过 JS 的人都踩过这个坑——CSS 属性读了半天还是个字符串,今天 CSS Typed OM 把这件事彻底原生化了
每次用 JS 读 CSS 属性都要和字符串打交道:el.style.opacity 返回的是字符串,不是数字。想做个简单的加法都要 parseFloat 转一圈。更坑的是,你以为自己在做加法:
el.style.opacity += 0.1; // 结果是字符串拼接,不是数值加法!
Firefox 155 稳定版把这件事彻底原生化了——CSS Typed OM 让所有 CSS 属性在你的 JS 里以类型化对象的形式存在,读出来是什么类型、写进去还是什么类型,数学运算不用再绕弯。
为什么字符串式的 CSSOM 一言难尽
传统 CSSOM 暴露的属性值全是字符串:
const width = div.style.width; // "200px",字符串
const opacity = window.getComputedStyle(div).opacity; // "0.5",字符串
这带来一连串问题:数值运算要手动 parse、字符串拼接 bug、单位处理靠猜、自定义属性读不到 computed 值。
Typed OM 核心:两种 StylePropertyMap
读 computed 样式:computedStyleMap()
const styleMap = element.computedStyleMap();
const opacity = styleMap.get("opacity");
console.log(opacity.value, opacity.unit); // 0.5, "number"
const width = styleMap.get("width");
console.log(width.value, width.unit); // 200, "px"
// 自定义属性也能读 computed 值
const brandColor = styleMap.get("--brand-color");
写行内样式:attributeStyleMap
element.attributeStyleMap.set("opacity", CSS.number(0.3));
element.attributeStyleMap.set("width", CSS.px(200));
element.attributeStyleMap.set("transform", CSS.rotate(45));
// 读出来是什么类型,加进去还是什么类型
const op = element.attributeStyleMap.get("opacity");
op.value += 0.1; // 0.4,不是字符串拼接
element.attributeStyleMap.set("opacity", CSS.number(op.value));
delete():终于可以删单个属性了
Firefox 155 新增的支持:
// 以前删样式只能 clear 全量
// element.attributeStyleMap.clear();
// 现在可以删一个
element.attributeStyleMap.delete("opacity");
// 配合 has/set,形成完整 CRUD
if (element.attributeStyleMap.has("opacity")) {
const op = element.attributeStyleMap.get("opacity");
element.attributeStyleMap.set("opacity", CSS.number(op.value * 0.8));
}
实际场景:动画插值
Typed OM 最有价值的场景是动画计算:
// 以前:手动 lerp + 字符串转换
const from = parseFloat(getComputedStyle(el).opacity);
el.style.opacity = String(from + (1 - from) * 0.5);
// Typed OM:直接操作 number
const fromVal = el.computedStyleMap().get("opacity").value;
el.attributeStyleMap.set("opacity", CSS.number(fromVal + (1 - fromVal) * 0.5));
兼容性
Chrome 66+ 从 2018 年就开始支持,Firefox 155 稳定版补全了 StylePropertyMap.delete()。Safari 暂未支持,约 70% 全球覆盖。建议渐进增强:
if (element.attributeStyleMap) {
element.attributeStyleMap.set("opacity", CSS.number(0.5));
} else {
element.style.opacity = "0.5";
}
下一步
如果你在写任何涉及 CSS 数值读写的 JS——动画、拖拽、resize 监听——先数一下代码里有多少 parseFloat。Typed OM 可以把这些全部替换掉,bug 会少很多。
评论区
0 条评论
登录后可评论。