Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【WIP】答 Winter 《我理想中的 HTML 和 CSS》 #21

Open
yisibl opened this issue Feb 21, 2025 · 2 comments
Open

【WIP】答 Winter 《我理想中的 HTML 和 CSS》 #21

yisibl opened this issue Feb 21, 2025 · 2 comments

Comments

@yisibl
Copy link
Owner

yisibl commented Feb 21, 2025

🚧 本文还在书写中,如有不足请多指教。

2010 年 @wintercn 老师在 W3C 中文 IG 里发出了《我理想中的 HTML 和 CSS》这封邮件,如今看来很多想法依然很有前瞻性。时间的齿轮滴答滴答的转动,十五年后网上「前端已死」的声音此起彼伏,那么就让我们来看看 Web 技术发展的到底如何了。

Style 可以控制所有交互

随着声明式组件浪潮的兴起,HTML 逐渐抢了很多 JS 的饭碗🍚,许多交互功能变成了通过 HTML 属性来控制和触发。

比如已经讨论了三四年的 Invoker Commands 功能,最近即将在 Chrome 中发布

  • command: 执行组件的某个方法。
  • commandfor:找到需要执行组件的 id。

这个示例可以通过纯 HTML 点击按钮,打开一个对话框:

<button command="show-modal" commandfor="my-dialog">This opens a dialog</button>
<dialog id="my-dialog">This is the dialog</dialog>

那么同样的,<input type=color> 中的颜色选择器、<select><video>popover 等都可以通过声明式的属性来控制行为。

如你所见,主要的活都被 HTML 抢去了,CSS 或许心有不甘,心想留点汤汤水水给我喝一喝也行啊。

虽然 CSSWG 对于在 CSS 加入控制交互的行为非常克制,但终究耐不住 Web 用户的需求高涨,还是加入了内卷的行列。比如最近 Chrome 推动的 interest-target-delay 属性,用来控制 popover 的延时显示和消失的时间。所以,「你还记得大明湖畔的夏雨荷么」?CSS 已不再是那个只负责展现层的 CSS 了。

不同的 CSS 单位直接可以互相运算

是的,CSS 现在可以通过 calc 混合运算单位,这是数学函数的基本操作:

.foo {
  width: calc(300px - 1cm + 10%);
}

稍有遗憾的是,目前带有单位的数值作为除数只有 Safari 支持,例如:calc( 200px / 10% * 1px)

使用 SVG 控制标签的形状

无论是在 CSS 中还是底层的计算机图形渲染,非矩形的绘制都是不容易的。目前已经初见成效:

border-shape 提案

苹果 WebKit 的人在积极推动的 border-shape提案,可以通过 SVG path 彻底自定义 border 样式的提案。

TODO: 截图

corner-shape 提案

此前,我们只能对边框做圆角,通过这个提案,边框可以是斜切,内凹。

Image

甚至未来支持苹果独有的曲率连续的圆角。这完成了工业设计特性在 Web 设计中的落地。也感谢苹果开放相关的算法和专利。

这是当前 CSS 圆角绘制曲率梳,可以看到与直线相接的地方,是不连续的。
Image

这是苹果圆角的曲率梳,过渡更加平滑

Image

对标 SVG path shape() 函数,但具有响应式

在此之前 SVG 中的 path 已经通过 shape()函数完成了语义化的迁移。

比如页面常见的气泡样式,之前我们只能通过 clip-path 来实现:

气泡

.bubble {
  clip-path: path("m 5 0 H 95 Q 100 0 100 5 V 92 Q 100 97 95 97 H 70 l -2 3 l -2 -3 H 5 Q 0 97 0 92 V 5 Q 0 0 5 0");
}

现在可以直接转换为等效的 shape() 函数:

.bubble { clip-path: shape(  from 5% 0%,
              hline to 95%,
              curve to 100% 5% with 100% 0%,
              vline to 92%,
              curve to 95% 97% with 100% 97%,
              hline to 70%,
              line by -2% 3%,
              line by -2% -3%,
              hline to 5%,
              curve to 0% 92% with 0% 97%,
              vline to 5%,
              curve to 5% 0% with 0% 0%);}

那么在 CSS 里重新实现 path 的意义是什么呢?我们知道 SVG 里的 path 是无法响应 CSS 单位的,而 shape 正是为此而生的。

在上述例子中,我们通常希望三角形部分始终为固定大小,圆角部分也是保持固定值,而矩形部分则可以根据容器或文本内容来自适应的。shape() 可以这样做:

.bubble { clip-path: shape(from 5px 0,
              hline to calc(100% - 5px),
              curve to right 5px with right top,
              vline to calc(100% - 8px),
              curve to calc(100% - 5px) calc(100% - 3px) with right calc(100% - 3px),
              hline to 70%,
              line by -2px 3px,
              line by -2px -3px,
              hline to 5px,
              curve to left calc(100% - 8px) with left calc(100% - 3px),
              vline to 5px,
              curve to 5px top with left top); }

更强大的是,它还可以和 CSS 变量一起使用,让你可以灵活配置细节参数。

pg.mp4
:root {
  --radius: 5px;
  --arrow-length: 3px;
  --arrow-half-width: 2px;
  --arrow-position: 70%;
  --arrow-bottom-offset: calc(100% - var(--radius) - var(--arrow-length));
}

.bubble {
  clip-path: shape(from var(--radius) top,
    hline to calc(100% - var(--radius)),
    curve to right var(--radius) with right top,
    vline to var(--arrow-bottom-offset),
    curve to calc(100% - var(--radius)) calc(100% - var(--arrow-length))
              with right calc(100% - var(--arrow-length)),
    hline to var(--arrow-position),
    line by var(--arrow-half-width) var(--arrow-length),
    line by var(--arrow-half-width) calc(-1 * var(--arrow-length)),
    hline to var(--radius),
    curve to left var(--arrow-bottom-offset) with left calc(100% - var(--arrow-length)),
    vline to var(--radius),
    curve to var(--radius) top with left top); }

我正在写一个工具,可以直接把 SVG path 转换为 CSS shape()

Image

@justjavac
Copy link

👍

@zhangenming
Copy link

Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants