DigitalOcean 提供适合您旅程各个阶段的云产品。立即开始使用 价值 200 美元的免费积分!
CSS position-try-fallbacks
属性接受一个包含不同选项的列表,这些选项用于“目标”元素相对于“锚点”元素进行position
定位,通过尝试声明的逗号分隔的选项列表来实现。如果第一个选项没有足够的可用空间来显示目标元素,则会尝试下一个选项,依此类推,这与在font-family
中设置备用字体非常类似。
.target {
position: absolute;
position-anchor: --my-anchor;
inset-area: top left;
position-try-fallbacks: flip-inline, inset-area(bottom left), --my-custom-position;
}
作为背景信息,这都是CSS 锚点定位规范的一部分,它是一套许多功能的集合,这些功能协同工作以定位一个元素(我们称之为“目标”)到另一个元素(我们称之为“锚点”)。
注意:CSS 规范将该属性称为position-try-fallbacks
,但截至本文撰写之时,Chromium 浏览器的实现称为position-try-options
,具有相同的取值集。未来,规范可能会更改,或者浏览器可能会更新其实现以保持一致。在此之前,建议使用position-try
简写属性。因此,本文中的所有演示都使用position-try-options
。
语法
position-try-fallbacks: none | [ [<dashed-ident> || <try-tactic>] | inset-area( <'inset-area'> ) ]#
- 初始值:none
- 应用于:绝对定位元素
- 继承:否
- 百分比:n/a
- 计算值:如指定
- 规范顺序:按语法
- 动画类型:离散
值
/* Custom @try-position */
position-try-fallbacks: --my-custom-position;
position-try-fallbacks: --myCustomPosition;
/* <try-tactic> */
position-try-fallbacks: flip-block;
position-try-fallbacks: flip-inline;
position-try-fallbacks: flip-start;
position-try-fallbacks: flip-block flip-inline;
/* `<dashed-ident>` || `<try-tactic>` */
position-try-fallbacks: --my-custom-position flip-block;
position-try-fallbacks: --myCustomPosition flip-block flip-inline;
/* inset-area( <'inset-area'> ) */
position-try-fallbacks: inset-area(bottom center);
position-try-fallbacks: inset-area(top left);
/* All can be together! */
position-try-fallbacks: --my-custom-position, flip-block flip-inline, --my-custom-position flip-block, inset-area(top left);
position-try-fallbacks
属性接受一个逗号分隔的选项列表,用于在目标元素超出其包含块时定位该元素。顺序按照书写顺序,但可以使用position-try-order
属性进行排序。
none:
将目标的定位选项列表清空。<dashed-ident>:
将一个自定义的@position-try
选项(具有给定名称)添加到选项列表中。如果不存在匹配的@position-try
,则该属性不会有任何效果。该值称为“虚线”标识符,因为它必须以两个连字符 (–) 为前缀。<try-tactic>:
通过沿三个轴之一翻转目标的当前位置来创建选项列表,每个轴都由一个不同的关键字定义。它们也可以组合起来,以累加其效果。<dashed-ident>
||<try-tactic>:
将一个自定义的@try-option
和一个<try-tactic>
组合在一起,通过按照指定的方式翻转自定义的@position-try
来创建一个单个选项列表。<try-tactic>
关键字也可以组合起来,以累加其效果。inset-area( <'inset-area'> ):
使用围绕包装函数的inset-area
语法将目标移动到新的inset-area
。
注意:根据规范,inset-area( <'inset-area'> )
函数不存在,inset-area
值不需要包装器,但已经实现了position-anchor
属性的浏览器仍然使用它。
position-try-options
为什么我们需要将元素相对于锚点进行定位似乎是一个两步操作: (1) 将目标链接到锚点元素,以及 (2) 将目标定位到锚点周围。但是,锚点元素可以位于页面上的任何位置,甚至由于滚动、缩放、动画等而改变位置。因此,目标元素很容易没有足够的空间相对于锚点进行定位,并超出其包含块(默认情况下为视窗)。
这是很正常的现象;我们无法阻止元素在滚动时超出屏幕,但我们可以通过最大化其屏幕显示时间来改善体验。
锚点定位的常见用例是工具提示,它们有一个反复出现的问题,即过多的超出屏幕显示。例如,位于元素顶部的工具提示在向下滚动时会超出屏幕。
传统上,避免这种情况的唯一方法是使用 JavaScript 动态更改工具提示的位置,但使用position-try-fallbacks
,我们只需要 CSS 就能实现相同的效果。
position-try-options
使用要在 CSS 中开始使用position-try-fallbacks
属性,我们需要我们的主要角色:锚点元素和目标元素。
<div class="anchor">My Anchor</div>
<div class="target">My Target</div>
以及一些 CSS 代码将它们链接在一起
.anchor {
anchor-name: --my-anchor;
}
.target {
position: absolute;
position-anchor: --my-anchor;
}
如果我们没有以任何特殊方式定位目标,它将停留在其默认锚点下方。我们可以使用anchor()
函数将目标沿着目标的内边距属性移动,或者使用inset-area
属性。无论您选择哪种选项,请记住它,以便稍后使用。
.target {
position: absolute;
position-anchor: --my-anchor;
inset-area: top;
/* or */
bottom: anchor(top);
}
我们的目标位于其锚点上方,但问题在于当我们向下滚动时,目标会向我们挥手告别,因为它消失在视窗之外。这个目标可能是一个工具提示或其他弹出窗口,用于显示有关其锚点元素的相关信息,但现在锚点可见,而其相关目标不可见。
这是一个由来已久的问题,最佳解决方案总是包括使用 JavaScript 来实现一个不会超出屏幕的工具提示,甚至使用像Popper.js 这样的库。
使用position-try-fallbacks
,我们可以编写一个包含可能位置的列表,以便在我们的目标超出视窗时使用。您的浏览器将按照书写顺序尝试这些选项,直到找到一个不会超出屏幕的选项,或者用完所有选项。
inset-area( <'inset-area'> )
为了简单起见,我们有inset-area()
包装函数,它接受您的常规inset-area
属性可以接受的所有值。我们可以给出一个包含可能inset-area
选项的列表,当目标超出屏幕时,它将尝试这些选项。例如,将目标从顶部移动到底部。
.target {
position: absolute;
position-anchor: --my-anchor;
inset-area: top;
position-try-fallbacks: inset-area(bottom);
}
我们还可以给出一个包含多个inset-area()
函数的列表,以便在需要时将目标在锚点周围移动
.target {
position: absolute;
position-anchor: --my-anchor;
inset-area: top left;
position-try-fallbacks:
inset-area(top), inset-area(top right),
inset-area(right), inset-area(bottom),
inset-area(bottom right);
}
<dashed-ident>
我们可以使用@position-try
at 规则来创建自定义的定位选项,以修改目标的位置。它接受几乎所有可以修改元素位置的属性
内边距属性 (
top
,left
,bottom
,right
,inset-block
,inset-inline
, 等)外边距属性 (
margin
,margin-block
,margin-inline
, 等)尺寸属性 (
width
,min-width
,height
,max-height
,inline-size
,block-size
, 等,)自身对齐属性 (
align-self
,justify-self
,place-self
)位置锚点属性 (
position-anchor
,inset-area
)
因此,例如,我们可以在目标超出屏幕时使其变小
@position-try --smaller-target {
width: 50px;
}
.target {
position: absolute;
position-anchor: --my-anchor;
inset-area: top;
position-try-fallbacks: --smaller-target;
width: 120px;
aspect-ratio: 1;
}
我告诉过您,如果使用内边距属性的anchor()
函数或inset-area
属性来定位锚点,请记住这一点。为什么?因为如果我们在原始声明中不一致,则使用@try-position
at 规则来更改它们将不起作用。例如,以下--custom-bottom
将不起作用,因为我们没有使用相同的方法来定位目标。
@position-try --custom-bottom {
width: 50px;
top: anchor(bottom);
}
.target {
/* ... */
inset-area: top;
position-try-fallbacks: --custom-bottom;
}
我们需要使定位方法匹配。
@position-try --custom-bottom {
width: 50px;
inset-area: bottom;
}
<try-tactic>
<try-tactic>
值根据指定的尝试策略交换其位置,从而创建一个新的位置选项。它有三个可能的关键词,每个关键词指定了哪些值将被交换,本质上是将目标从一侧更改到另一侧。
flip-block
关键词交换块轴中的值。
flip-inline
关键词交换内联轴中的值。
flip-start
关键词对角线交换值。我不得不承认,flip-start
是一个奇怪的 <try-tactic>
,对我来说仍然有点令人困惑。在单个值的情况下,它会将它们定位在相邻的一侧。
但如果目标有两个值,它会将它们定位在对角的角落。至少在理论上,在实践中,它只能将目标从右上角翻转到左下角,反之亦然,在 LTR 上。
以及从左上角翻转到右下角,反之亦然,在 RTL 上。
如果我们想要一个无论文本方向如何都能翻转到对角角落的目标,我们可以组合 flip-block
和 flip-inline
关键词。它将首先在块轴上翻转锚点,然后在内联轴上翻转。
最后,我们可以将 flip-start
值与 flip-block
或 flip-inline
组合,将目标翻转到另一个相邻的一侧。
顺序很重要,所以编写 flip-start flip-block
将导致与 flip-block flip-start
不同的位置。在后者中,flip-block
关键词首先执行,由于目标不在块轴上,因此它没有任何效果,并且被忽略。
<dashed-ident>
|| <try-tactic>
最后,我们可以将一个自定义 @try-position
选项与一个或多个 <try-tactic>
关键词组合起来,创建一个新的位置选项,本质上是翻转 @try-position
属性。例如,自定义位置选项……
@try-position --custom-right {
inset-area: top;
align-self: start;
}
……如果使用 flip-block
关键词翻转,将计算为以下结果
@try-position --custom-right {
inset-area: bottom;
align-self: end;
}
演示
规范
position-try-options
属性在 CSS 锚点定位模块 1 级规范 中定义,该规范目前处于工作草案状态。这意味着在该功能成为正式候选推荐以供实施之前,可能会有很多变化。
浏览器支持
更多信息和教程
- “CSS 锚点定位” (CSSWG)
- “介绍 CSS 锚点定位 API” (Una Kravets)
- “CSS 中我兴奋的新东西 - 上次 CSSWG 会议后” (Juan Diego Rodríguez)