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)
 
      