跳转至

Anchor 插件

Alpine 的 Anchor 插件允许你轻松地将一个元素的位置锚定到页面上的另一个元素。

这个功能在创建下拉菜单、弹出框、对话框和使用 Alpine 的提示框时非常有用。

该插件使用的"锚定"功能由 Floating UI 项目提供。

安装

你可以通过 <script> 标签引入或通过 NPM 安装来使用此插件:

通过 CDN

你可以将此插件的 CDN 构建版本作为 <script> 标签引入,只需确保在 Alpine 核心 JS 文件之前引入。

<!-- Alpine 插件 -->
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/anchor@3.x.x/dist/cdn.min.js"></script>

<!-- Alpine 核心 -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>

通过 NPM

你可以从 NPM 安装 Anchor 以在打包中使用:

npm install @alpinejs/anchor

然后从你的打包工具中初始化它:

import Alpine from 'alpinejs'
import anchor from '@alpinejs/anchor'

Alpine.plugin(anchor)

...

x-anchor

使用此插件的主要 API 是 x-anchor 指令。

要使用此插件,将 x-anchor 指令添加到任何元素,并传入要锚定位置的元素的引用(通常是页面上的一个按钮)。

默认情况下,x-anchor 会将元素的 CSS 设置为 position: absolute 以及适当的 topleft 值。如果被锚定的元素通常显示在参考元素下方但没有足够空间,它的样式将被调整以显示在元素上方。

例如,这里有一个简单的下拉菜单,锚定到切换它的按钮:

<div x-data="{ open: false }">
    <button x-ref="button" @click="open = ! open">Toggle</button>

    <div x-show="open" x-anchor="$refs.button">
        Dropdown content
    </div>
</div>
Dropdown content

定位

x-anchor 允许你使用以下修饰符自定义锚定元素的定位:

  • 底部:.bottom.bottom-start.bottom-end
  • 顶部:.top.top-start.top-end
  • 左侧:.left.left-start.left-end
  • 右侧:.right.right-start.right-end

以下是一个使用 .bottom-start 将下拉菜单定位在参考元素下方并靠右对齐的示例:

<div x-data="{ open: false }">
    <button x-ref="button" @click="open = ! open">Toggle</button>

    <div x-show="open" x-anchor.bottom-start="$refs.button">
        Dropdown content
    </div>
</div>
Dropdown content

固定定位

默认情况下,x-anchor 对锚定元素应用 position: absolute。这在大多数情况下没问题,但当参考元素位于带有 overflow: hiddenoverflow: clipoverflow: auto 的容器内时,锚定元素会随之被裁剪。

你可以通过添加 .fixed 修饰符来指示 Floating UI 改用固定定位策略:

<div x-data="{ open: false }">
    <button x-ref="button" @click="open = ! open">Toggle</button>

    <div x-show="open" x-anchor.fixed="$refs.button">
        Dropdown content
    </div>
</div>
Dropdown content

注意: 任何祖先元素上的 transformfilterperspectivebackdrop-filterwill-changecontain 都会为 position: fixed 后代元素创建一个新的包含块(根据 CSS 规范)。发生这种情况时,.fixed 将相对于该祖先元素表现为 position: absolute,并且无法逃脱其 overflow: hidden。如果 .fixed 似乎不起作用,请检查是否有应用了 transform 的祖先元素。

偏移量

你可以使用 .offset.[px 值] 修饰符为锚定元素添加偏移量,如下所示:

<div x-data="{ open: false }">
    <button x-ref="button" @click="open = ! open">Toggle</button>

    <div x-show="open" x-anchor.offset.10="$refs.button">
        Dropdown content
    </div>
</div>
Dropdown content

防止翻转位置

默认情况下,如果锚定元素在参考元素下方没有足够的空间渲染,x-anchor 会翻转其位置。

你可以通过添加 .noflip 修饰符来阻止此行为:

<div x-data="{ open: false }">
    <button x-ref="button" @click="open = ! open">Toggle</button>

    <div x-show="open" x-anchor.noflip="$refs.button">
        Dropdown content
    </div>
</div>
Dropdown content

手动样式

默认情况下,x-anchor 会在内部将定位样式应用到你的元素。如果你更希望完全控制样式,可以传递 .no-style 修饰符,并使用 $anchor 魔法在另一个 Alpine 表达式中访问这些值。

以下是一个绕过 x-anchor 内部样式,转而使用 x-bind:style 自行应用样式的示例:

<div x-data="{ open: false }">
    <button x-ref="button" @click="open = ! open">Toggle</button>

    <div
        x-show="open"
        x-anchor.no-style="$refs.button"
        x-bind:style="{ position: 'absolute', top: $anchor.y+'px', left: $anchor.x+'px' }"
    >
        Dropdown content
    </div>
</div>
Dropdown content

结合 .no-style.fixed 当你选择不使用 Alpine 的内部样式并希望使用固定定位时,记得自己设置 position: 'fixed'$anchor.x$anchor.y 根据当前激活的策略返回坐标空间中的值——绝对坐标相对于偏移父元素,固定坐标相对于视口——因此应用错误的 position 会使元素显示在错误的位置。

<div
    x-show="open"
    x-anchor.no-style.fixed="$refs.button"
    x-bind:style="{ position: 'fixed', top: $anchor.y+'px', left: $anchor.x+'px' }"
>
    Dropdown content
</div>

锚定到 ID

到目前为止的示例都是使用 Alpine refs 锚定到其他元素。

因为 x-anchor 接受任何 DOM 元素的引用,你可以使用像 document.getElementById() 这样的工具来通过其 id 属性锚定到一个元素:

<div x-data="{ open: false }">
    <button id="trigger" @click="open = ! open">Toggle</button>

    <div x-show="open" x-anchor="document.getElementById('trigger')">
        Dropdown content
    </div>
</div>
Dropdown content