首页 >web前端 >css教程 >另一个锚定位怪癖

另一个锚定位怪癖

Christopher Nolan
Christopher Nolan原创
2025-03-07 16:54:12409浏览

Yet Another Anchor Positioning Quirk

CSS锚点定位:一个令人惊喜的功能,但也存在一些棘手的问题。虽然不像Flexbox或Grid那样彻底改变游戏规则,但它填补了数十年来CSS定位中的空白。然而,它也有一些独特的特性,导致了一些令人费解的行为。本文将探讨一个困扰我已久的锚点定位问题。

起源

一个月前,我在阅读他人使用锚点定位的案例时发现了这个问题,特别是Temani Afif关于“锚点定位和滚动驱动动画”的文章。强烈建议您阅读这篇文章,看看是什么引起了我的注意。他巧妙地结合了锚点定位和滚动驱动动画,制作了一个在进度变化时颜色也会改变的范围滑块。

更令人惊奇的是,他使用了两个具有相同锚点名称的目标元素,每个元素都附加到其对应的锚点上,如同魔法一般。如果这看起来并不那么有趣,那么我们应该简要回顾一下锚点定位的工作原理。

CSS锚点定位和anchor-scope属性

请参阅我们的完整CSS锚点定位指南,以获得更深入的了解。

锚点定位为CSS带来了两个新概念:锚点元素和目标元素。锚点是用于定位其他元素的参考元素。目标元素是相对于一个或多个锚点进行绝对定位的元素。

锚点和目标几乎可以是任何元素,您可以将它们视为并排放置的两个div:

<code><div>anchor</div>
<div>target</div></code>

首先,我们必须使用anchor-name属性在CSS中注册锚点元素:

<code>.anchor {
  anchor-name: --my-anchor;
}</code>

然后,在绝对定位的元素上使用position-anchor属性将其附加到具有相同名称的锚点。但是,要移动锚点周围的目标,我们需要position-area属性。

<code>.target {
  position: absolute;
  position-anchor: --my-anchor;
  position-area: top right;
}</code>

这很好用,但是如果我们更改标记以包含更多锚点和目标,情况就会变得复杂:

<code></code>
  • anchor 1
    target 1
  • anchor 2
    target 2
  • anchor 3
    target 3

目标元素不会附加到其最近的锚点,而是全部堆积在DOM中最后注册的锚点上。

anchor-scope属性在Chrome 131中引入,用于解决此问题。它将锚点的范围限制到子树,以便每个目标正确附加。但是,我不想关注此属性,因为最初引起我注意的是Temani没有使用它。出于某种原因,所有目标都正确附加,再次像魔法一样。

发生了什么?

目标通常附加到DOM中的最后一个锚点,而不是其最近的锚点,但在我们的第一个示例中,我们看到了两个具有相同anchor-name的锚点及其对应的附加目标。所有这些都没有使用anchor-scope属性。发生了什么?

两个词:包含块

关于锚点定位需要注意的是,它很大程度上依赖于元素包含块的构建方式。这并非锚点定位本身固有的特性,而是绝对定位的特性。绝对定位的元素相对于其包含块进行定位,而像top: 0pxleft: 30pxinset: 1rem这样的内边距属性只是在包含块边界周围移动元素,创建所谓的内边距修改后的包含块

附加到锚点的目标没有什么不同,position-area属性在底层所做的就是更改目标的内边距修改后的包含块,使其紧挨着锚点。

通常,绝对定位元素的包含块是整个视口,但可以通过任何位置属性非static的祖先元素(通常是relative)来更改。Temani利用了这一事实,为每个滑块创建了一个新的包含块,因此它们只能附加到其对应的锚点。如果您查看代码,您可以在开头找到它:

<code><div>anchor</div>
<div>target</div></code>

如果我们在之前的示例中使用此策略,它们就会突然正确附加!

另一个问题

我们不需要使用anchor-scope属性将每个锚点附加到其各自的目标,而是利用了如何计算绝对元素的包含块。但是,还有另一种方法,不需要任何额外的代码。

当我同时试验滚动驱动动画和锚点定位并尝试将文本气泡脚注附加到帖子的侧面时,我发现了这一点,如下所示:

逻辑上,每个脚注都是一个目标,但锚点的选择有点棘手。我最初认为每个段落都可以作为锚点,但这意味着将有多个具有相同anchor-name的锚点。结果:所有目标都将堆积在最后一个锚点上:

这可以通过我们之前为每个注释创建新包含块的方法来解决。但是,我们还可以采取另一种方法,我称之为还原论方法。当有多个具有相同anchor-name的锚点时,问题就出现了,因此我们将锚点的数量减少到一个,使用一个可以作为所有目标的公共锚点的元素。

在这种情况下,我们只想将每个目标定位在帖子的两侧,因此我们可以使用帖子的整个主体作为锚点,并且由于每个目标自然地在垂直轴上对齐,剩下的就是沿着水平轴移动它们:

您可以更好地检查原始帖子是如何完成的!

结论

anchor-scope可能是最近发布到浏览器(到目前为止,仅在Chrome 131 中)的CSS属性,因此我们不能指望它的支持会超出预期。虽然我很想随时随地使用它,但在一段时间内它仍将局限于简短的演示。这不是限制使用其他锚点定位属性的理由,这些属性在Chrome 125及更高版本中受支持(并希望在不久的将来在其他浏览器中受支持),因此我希望这些小问题可以帮助您毫无顾虑地继续使用锚点定位。

以上是另一个锚定位怪癖的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn