CSS 与布局 / 圆角三部曲:一个角的二十年 / border-radius 之后:corner-shape 与超椭圆 待审核 3 / 5
corner-shape · 圆角之后

border-radius 之后:corner-shape 与超椭圆

border-radius 能画的弧本质都是圆或椭圆的一段。想要切角(bevel)、凹角(scoop)、缺口(notch),或 Apple 图标那种更饱满的方圆(squircle),过去只能回到 clip-path 甚至切图。corner-shape(CSS Borders Level 4)给出统一答案:它不改半径,只在同一个 border-radius 上换掉这段曲线的形状,而所有形态背后是同一个数学对象——超椭圆(superellipse)。

§1 与 §2 的演示各配一份 SVG 手绘预览,用路径画出同样的形状,不支持 corner-shape 的浏览器也能看原理;§3 的逐角组合只有真实 CSS 渲染。

1 · corner-shape 与半径的分工

corner-shape 必须配合非零的 border-radius:半径定义了角区域有多大,corner-shape 决定在这块区域里画哪种曲线。若元素没有 border-radius,或它解析为 0corner-shape 不产生任何效果 [1]。

图 1-1 · 左为真实 CSS 渲染(需支持 corner-shape),右为处处可见的 SVG 手绘预览。可拖半径、切形态,或用 superellipse() 滑块做连续变形。

注 · 半径为 0 时无论选哪种形态都是直角,因为没有角区域可供作画。corner-shape 改的是这块区域里曲线的凹凸,区域大小由 border-radius 决定,两者各管一半。

2 · 超椭圆的单参数族

六个关键字是同一条 superellipse(K) 曲线在不同 KK 上的取值。它由椭圆方程改一个指数得来:把 x2+y2=1x^2 + y^2 = 1 里的 2 换成 2K2^K,得

x2K+y2K=1x^{2^K} + y^{2^K} = 1

于是 K=1K = 1 给指数 2,是普通圆弧;K=0K = 0 给指数 1,是两切点之间的直线;K=2K = 2 给指数 4,比圆更饱满;KK \to \infty 时趋近直角 [2]。

KK 给出凹曲线,但它不是「指数小于 1 的 Lamé 曲线」。规范的说法是:负值的超椭圆与其相反数的超椭圆呈对称 [2],即 K=1K = -1 的 scoop 是 K=1K = 1 圆弧的镜像。core/superellipse.ts 按这个语义实现,凹侧仍取指数 2K2^{|K|} 的曲线,再把参数化的两个分量各自换成 1t1 - t

这个区别可以量出来。以角区域的边长为 1、角顶点为原点,取曲线在对角线上的那个点:KK221100 时引擎给 0.1590.1590.2930.2930.5000.500,与照字面代入 x2K+y2K=1x^{2^K} + y^{2^K} = 1 算出的值完全重合;但 K=1K = -1 时引擎给 0.7070.707、字面代入给 0.7500.750K=2K = -2 时引擎给 0.8410.841、字面代入给 0.9380.938。引擎那两个数恰好是 10.2931 - 0.29310.1591 - 0.159,即同一 K|K| 凸弧深度的补——镜像语义在数值上就长这样。

图 2-1 · 单个角的轮廓随 KK 连续变形。可扫 KK 从负端的方形缺口一路看到正端的方角。

2.1 · 关键字与 superellipse 的对应

round / bevel 等只是常用取值的别名,superellipse() 可填任意实数(含 infinity-infinity),因此能连续动画。负 KK 一列的指数指的是被反射的那条凸曲线。
keyword = superellipse 曲线指数 2K2^K 形态
square superellipse(infinity) \to \infty 直角,角区域内的极限凸
squircle superellipse(2) 44 比圆更饱满的方圆,Apple 图标的轮廓
round superellipse(1) 22 普通圆弧,等同 border-radius 默认
bevel superellipse(0) 11 两切点之间的直线切角
scoop superellipse(-1) 22,反射 向内凹的弧,圆弧的镜像
notch superellipse(-infinity) \to \infty,反射 90° 向内的方形缺口

建议 · 想把圆角拉直成尖角或切角时,找的不是某个 border-sharp 之类的属性——那并不存在。切角是 corner-shape: bevel(直线),极限直角是 square,向内的尖缺口是 notch,它们都在 corner-shape 这一条参数轴上。另有一个 border-shape 属性用于直接给整个边框画自定义形状;一旦设置它,border-radius 会被忽略,依赖半径的 corner-shape 也随之失效 [1]。

3 · 逐角组合

border-radius 一样,corner-shape 接 1~4 个值(TL → TR → BR → BL 顺时针),也有 corner-top-left-shape 等 longhand、corner-top-shape 之类的边 shorthand 以及逻辑属性。让不同角用不同形态,就能拼出票根、缺口卡片等过去要靠 mask 或 SVG 才能做的造型。

图 3-1 · 四个角各取不同形态的组合,仅真实 CSS 渲染。可点选预设或逐角改形态。

警示 · corner-shape 仍是实验特性,仅 Chromium 139+(2025-08)落地,Firefox 与 Safari 均未实现,尚未进入 Baseline(兼容性据 MDN BCD,核对于 2026-08)。稳妥写法是默认就给一个像样的 border-radius 圆角,再用 @supports (corner-shape: scoop) { … } 把高级形态作为增强叠加,不支持的浏览器退回普通圆角而非破版。

注 · 设在容器上的 background-colorbackground-imageborderoutlinebox-shadowoverflowbackdrop-filter 都会跟随角的形状 [1]。内容的排布仍相对原来的方形盒子,所以文字可能探出凹角之外。

切图滑动门一行 border-radius,再到 corner-shape 把曲率本身变成连续参数,二十年里一个圆角从固化的图片资产变成了可计算、可继承、可动画的声明式样式。只改四个角一页用同一套参数拼出扇形、叶形、房子等造型。

4 · 参考文献

  1. MDN Web Docs. corner-shape(含与 border-shape 的交互、跟随角形状的属性清单与对角约束). Mozilla.
  2. MDN Web Docs. superellipse()x2K+y2K=1x^{2^K} + y^{2^K} = 1 与负值的对称语义). Mozilla.
  3. Atkins, T., et al. (Eds.). CSS Borders and Box Decorations Module Level 4, §funcdef-superellipse. W3C.