
CSS 使用许多所谓的标识view-transition-name来命名事物——想想您为、、等输入view-timeline-name的值。container-name
一次性为大量元素构建这些唯一值通常是一项重复性工作,其中你会发现自己*-name要为每个元素重复选择器和声明。有 100 个元素?那就是 100 个声明(作为 100 条规则的一部分)。呃。
刚刚发布的一项 CSS 工作组决议采纳我为解决此问题所提出的一个方案:函数ident()。
在许多CSS 功能中,您需要为元素指定一个特定的名称,以便以后可以引用这些元素。例如container-name,,,,等。view-transition-nameview-timeline-namescroll-timeline-name
根据属性的不同,这些名称可能是<custom-ident>或<dashed-ident>。这些名称必须是唯一的(在使用的功能范围内)。对于视图转换和滚动驱动动画,这种唯一性可能会成为作者的负担。
以这个滚动驱动动画为例,我为每个目标元素设置了一个独特的view-timeline-name(<dashed-ident<适合场合的)时间轴,稍后也会参考该时间轴:
.parent {
timeline-scope: all;
}
main {
div:nth-child(1) { view-timeline-name: --tl-1; }
div:nth-child(2) { view-timeline-name: --tl-2; }
div:nth-child(3) { view-timeline-name: --tl-3; }
}
nav {
li:nth-child(1) { animation-timeline: --tl-1; }
li:nth-child(2) { animation-timeline: --tl-2; }
li:nth-child(3) { animation-timeline: --tl-3; }
}与 View Transitions 相同,我曾看到过此代码:
&:nth-child(1) {
view-transition-name: opt-1;
& > label {
view-transition-name: opt-1-label;
}
& > input {
view-transition-name: opt-1-input;
}
}
&:nth-child(2) {
view-transition-name: opt-2;
& > label {
view-transition-name: opt-2-label;
}
& > input {
view-transition-name: opt-2-input;
}
}
&:nth-child(3) {
view-transition-name: opt-3;
& > label {
view-transition-name: opt-3-label;
}
& > input {
view-transition-name: opt-3-input;
}
}虽然这两个例子都仅限于 3 个项目,但你可以很容易地发现,当涉及更多项目时,这会成为一种负担。
解决方案:ident()
为了便于批量命名元素,我向 CSS 工作组提出了该函数。这是一个动态构造和值的函数。ident()<custom-ident><dashed-ident>
<ident()> = ident( <ident-arg>+ ) <ident-arg> = <string> | <integer> | <ident>
该函数接受任意数量的空格分隔的参数,但至少需要 1 个。参数的类型为<string>,<integer>或其他<ident>。该函数的结果是<ident>由传入的参数连接在一起组成的。
例如,使用sibling-index(),之前分享的第一个示例可以重写如下:
.parent {
timeline-scope: all;
}
nav li {
animation-timeline: ident("--tl-" sibling-index()); /* --tl-1, --tl-2, … */
}
main div {
view-timeline-name: ident("--tl-" sibling-index()); /* --tl-1, --tl-2, … */
}无论标记中使用了多少元素,此代码都会自动缩放。
更多示例
ident()当您将该函数与其他函数/特性结合使用时,该函数会大放异彩。我已经提到过sibling-index(),另一个这样的函数是attr()您可以使用它将 HTML 属性的值导入 CSS 的函数。
例如:
.item {
view-timeline-name: ident("--item-" attr(id) "-tl");
}
label {
animation-name: ident("--item-" attr(for) "-tl");
}对于具有像、和 这样的s.item的元素;结果s 分别为、和。idbeachhousebikeview-timeline-name--item-beach-tl--item-house-tl--item-bike-tl
或者这里有一个更高级的示例,它首先id从中读取属性.card并将其存储到自定义属性中。由于自定义属性在继承之前计算,因此子级可以很好地引用该自定义属性。
.card[data-view-transition-id] {
--id: attr(data-view-transition-id); /* E.g. card1, card2, card3, … */
view-transition-name: var(--id);
view-transition-class: card;
h1 {
view-transition-name: ident(var(--id) "-title"); /* E.g. card1-title, card2-title, card3-title, … */
view-transition-class: card-title;
}
.content {
view-transition-name: ident(var(--id) "-content"); /* E.g. card1-content, card2-content, card3-content, … */
view-transition-class: card-content;
}
}常问问题
作为今天 CSS WG 讨论的一部分,我准备了一份常见问题的简短列表:
为什么我们需要函数?难道不能直接把所有东西粘合在一起吗?例如view-transition-name: var(--id) "title";?
解析目的。想想简写,例如scroll-timeline,很难检测到它所包含的全写。
如果ident()不明确标识由哪些部分组成:
scroll-timeline: inline "tl-" var(--id)scroll-timeline: "tl-" var(--id) inline
很清楚的知道ident()什么是组合:
scroll-timeline: inline ident("tl-" var(--id))scroll-timeline: ident("tl-" var(--id)) inline
为什么不使用重新设计的attr()可以解析标识的版本?例如attr(foo type(<custom-ident>))?
该ident()功能不止于此atrr(),它还允许您将多段字符串粘合在一起,例如ident("view-" attr(data-vt-id))或ident("view-" attr(data-type) "-" attr(data-sequence))。
需要粘合的部件也可以来自其他元素,通过将它们存储到自定义属性中。
那么构造<dashed-ident> 怎么样?
放在"--"开头,例如ident("--item-tl-" attr(data-itemnum))
是否需要添加该attr()函数(这会使你的例子看起来更短)? type(<custom-ident>)
否,当未<attr-type>指定时,<attr-name>将被解析为 CSS 字符串。由于也ident()设计为接受<string>值,因此它可以正常工作。
为什么不依赖类似…-name: auto自动生成标识的东西呢?
解决方案的问题…-name: auto在于:
这些仅适用于特定功能,但
ident()可以用于所有使用标识的功能。它们会生成一个您无法观察到的标识。这意味着您以后无法引用该生成的标识。对于容器、滚动时间轴等功能,您需要能够从标记中的其他地方引用该标识。
它们只对目标元素本身有意义。
ident()您可以将值存储在自定义属性中,以将值传递给子元素。当多个元素需要使用相同的标识时(在页面生命周期的不同时间),这种方法不起作用。请参阅https://codepen.io/bramus/pen/PogVZwb等理想演示,其中
title-item-1生成的名称有条件地应用于两个不同的元素。
所提出的方案ident()没有这些限制;它超越了像这样的每个功能解决方案…-name: auto。






网友评论文明上网理性发言 已有0人参与
发表评论: