写过前端的人都踩过这个坑——斜切布局每次都要靠 skew 硬撑,圆形排布要用 JS 算坐标。今天三个 CSS 三角函数把这件事彻底原生化了
配前端这些年,做斜切 banner 只能用 skewX 硬撑,角度一变就要重新算偏移量;做圆形菜单要把 8 个 item 的坐标一个个在 JS 里 Math.sin/Math.cos 算出来再灌回 CSS。三角函数早就在脑子里想过,就是 CSS 不支持。
2023 年开始,sin()、cos()、tan() 三个函数正式进了 CSS Values and Units Level 4,Chrome 111+、Firefox 108+、Safari 15.4+ 全部支持,全球约 93% 覆盖。这些场景不用再找 JS 了。
斜切 banner:角度变了自己会算
斜切 banner 是最常见的场景。以前要么写死一个 tan 值硬塞进 padding,要么用 JS 动态算:
/* 以前:magic number 靠 JS 算出来 */
.banner { --angle: 10deg; padding-top: calc(tan(11deg) * 50vw); } /* JS: padding-top = width * tan(angle) */
现在一行 CSS:
.banner { --angle: 10deg; --w: 100vw; padding-top: calc(tan(var(--angle)) * var(--w) / 2); }
角度改 –angle 一个变量,padding 自动跟着变。9elements 博客把这个思路系统化成了一套 diagonal layout 方案,2020 年发的时候还只能用 magic number;2023 年之后直接上 tan(),magic number 消失了。
平行四边形也是同理:用 tan() 算好宽度偏移量,直接决定 ::before 的宽度:
.parallelogram { --w: 400; --h: 200; --angle: 20deg; }
.parallelogram::before { width: calc(100% - 100% * var(--h) / var(--w) * tan(var(--angle))); transform: skewX(calc(0deg - var(--angle))); }
圆形排布:坐标直接出
把 8 个元素排成一圈,以前要这样:
// JS 算坐标然后塞进 style
items.forEach((item, i) => {
const angle = (360 / items.length) * i * Math.PI / 180;
item.style.left = `calc(50% + ${Math.cos(angle) * radius}px)`;
item.style.top = `calc(50% + ${Math.sin(angle) * radius}px)`;
});
现在纯 CSS:
.orbit-dot { --angle: calc(var(--i) / var(--total) * 360deg); --r: 100px; left: calc(50% + cos(var(--angle)) * var(--r)); top: calc(50% + sin(var(--angle)) * var(--r)); transform: translate(-50%, -50%); }
–angle、–r 都是 CSS 变量,改总数量或半径,整个布局自动重排。设计工具里那些精致的 loading 动画、Splash 页面入口动画,现在可以零 JS 实现。
atan2() 反过来用
sin/cos 是「已知角度求坐标」,atan2() 做的是反过来:「已知两个坐标差求角度」。用这个可以做鼠标跟随角度、自适应箭头指向等:
.arrow { --dx: 50; /* 目标相对 x */ --dy: 30; /* 目标相对 y */ rotate: atan2(var(--dy), var(--dx)); }
浏览器支持
Chrome 111+、Edge 111+、Firefox 108+、Safari 15.4+。2023 年 3 月全面稳定,Baseline 2023 全球覆盖约 93%。对低端设备可以写 @supports 渐进增强:
.diagonal-section { @supports (top: calc(tan(10deg) * 50vw)) { /* 三角函数可用 */ } }
下一步
如果你现在手头有斜切布局、圆形导航、扇形菜单这些组件,看看它们有多少行 JS 在算坐标——那些代码可以全部删掉,换成三行 CSS 变量加 sin/cos/tan。
评论区
登录后可评论。