×

CSS 的未来:使用 ident() 构造 和 值

作者:Sanakey2025.02.08来源:Web前端之家浏览:280评论:0

image.png

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

您的支持是我们创作的动力!
温馨提示:本文作者系 ,经Web前端之家编辑修改或补充,转载请注明出处和本文链接:
https://jiangweishan.com/article/cssgouczaozhicfd.html

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

发表评论: