アンカー位置指定タブの下線

タブメニューでは、ユーザーがどのページにいるかを視覚的に示す必要があります。1 つ目の方法は、タブに下線を引くことです。アンカー ポジショニングを使用すると、下線の位置の間にスムーズなアニメーションを作成できます。アクティブなタブを変更すると新しいウェブページが読み込まれる場合は、この操作は機能しません。

このエフェクトを使用して、垂直タブバーのアクティブなタブを示すアニメーション ドットを追加することもできます。

<li> 要素を含む <ul> で ::before 疑似要素を使用して下線を作成します。疑似要素を使用する方法は、DOM をクリーンに保ち、純粋に装飾的な効果のために余分な要素を追加することを回避できるため、推奨されるアプローチです。

ul::before {
  /* Use a pseudo-element on the container to represent the animated indicator */
  content: '';
}

anchor-name プロパティを追加して、アクティブなリストアイテムをアンカーにします。このプロパティの値は -- で始まります。

li.active {
  /* Make a unique anchor-name for the active element. */
  anchor-name: --active;
}

アンカーの anchor-name と一致する position-anchor を使用して、下線をアクティブなアイテム アンカーに固定し、position: absolute にします。

ul::before {
  /* Tether the underline to the active element. */
  position: absolute;
  position-anchor: --active;
}

インセット プロパティと anchor() 関数を使用して、アンカーを基準に下線を配置します。

ul::before {
  /* DO NOT use position-area, which can not be transitioned. */
  /* Use calc() to offset the top slightly */
  inset-block-start: calc(anchor(bottom) + .1lh);
  inset-inline-start: anchor(left);
  inset-inline-end: anchor(right);
}

高さやその他の視覚スタイルを追加します。

ul::before {
  /* Apply your project's styles for the indicator */
  block-size: .25lh;
  background: red;
}

最後に、inset プロパティに遷移を追加します。

ul::before {
  @media (prefers-reduced-motion: no-preference) {
    /* MANDATORY: The transition must be wrapped in a prefers-reduced-motion media query to respect user preferences. */
    transition: inset .2s;
  }
}

これは視覚的なインジケーターにすぎず、適切な aria-current="page" または aria-selected aria 値の設定に代わるものではありません。

<!-- MANDATORY: Provide explicit assistive technology state alongside the visual tab underline -->
<nav aria-label="Primary">
  <ul>
    <li class="active">
      <a href="/home" aria-current="page">Home</a>
    </li>
    <li>
      <a href="/about">About</a>
    </li>
  </ul>
</nav>

代替戦略

ブラウザでアンカーの配置がサポートされていない場合は、border-bottom を使用して下線を追加します。アニメーションは表示されません。

ul li.active {
  @supports not (position-anchor: auto) {
    /* Choose a color appropriate to the app theme. */
    border-bottom: .25lh var(--primary) solid;
  }
}