スマート追従ヘッダ
stimeo--smart-sticky-header
下スクロールで隠れ、上スクロールで現れるヘッダ(フォーカス到達では必ず表示)。
stimeo--smart-sticky-header は、stimeo--sticky-observer にあえて無い「方向の感覚」を足します。offset を超えた下スクロールで data-header-hidden="true" を公開し、上スクロール(tolerance のジッタガード超)または offset 以内への復帰で表示に戻し、そしてヘッダへのフォーカス到達では必ず表示します — 隠れたヘッダに Tab で入ったキーボードユーザーがフォーカス先を見失わないため(WCAG 2.4.7 / 2.4.11)。退避の transform と reduced-motion 対応は消費側 CSS の責務です。スクロール源は既定でウィンドウ、オーバーフローコンテナ内のヘッダには containerSelector を指定します(このデモがその構成です)。
枠の中を下へスクロールするとバーが退避し、上へスクロール — または Tab で入る — と戻ってきます。
<%# smart-sticky-header: the library only flips data-header-hidden from the scroll
direction (and reveals on focus); the slide-away is this demo's CSS transform.
Scroll down inside the frame to hide the bar, up (or Tab into it) to reveal. %>
<div class="smart-sticky-demo">
<p class="smart-sticky-demo__hint"><%= t("components.smart_sticky_header.demo.hint") %></p>
<div id="smart-sticky-viewport" class="smart-sticky-demo__viewport" role="region" tabindex="0"
aria-label="<%= t('components.smart_sticky_header.demo.viewport_label') %>">
<header class="smart-sticky-demo__header" data-controller="stimeo--smart-sticky-header"
data-stimeo--smart-sticky-header-container-selector-value="#smart-sticky-viewport"
data-stimeo--smart-sticky-header-offset-value="40">
<a href="#smart-sticky-demo-content"><%= t("components.smart_sticky_header.demo.brand") %></a>
</header>
<div id="smart-sticky-demo-content" class="smart-sticky-demo__content">
<% 10.times do |i| %>
<p><%= t("components.smart_sticky_header.demo.paragraph", index: i + 1) %></p>
<% end %>
</div>
</div>
</div>
/*
* Presentation-only styles for the smart-sticky-header demo. The library flips
* data-header-hidden; the slide-away transform (and its reduced-motion opt-out)
* lives here. The controller is pointed at the demo's own scroll frame via
* containerSelector (the catalog page itself does not scroll).
*/
.smart-sticky-demo__hint {
margin: 0 0 0.75rem;
color: var(--muted);
}
.smart-sticky-demo__viewport {
position: relative;
height: 16rem;
overflow-y: auto;
border: 1px solid var(--border);
border-radius: 0.5rem;
}
.smart-sticky-demo__viewport:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
.smart-sticky-demo__header {
position: sticky;
top: 0;
padding: 0.75rem 1rem;
background: var(--bg);
border-bottom: 1px solid var(--border);
transition: transform 0.2s ease;
}
.smart-sticky-demo__header[data-header-hidden="true"] {
transform: translateY(-100%);
}
@media (prefers-reduced-motion: reduce) {
.smart-sticky-demo__header {
transition: none;
}
}
.smart-sticky-demo__content {
padding: 1rem;
}
.smart-sticky-demo__content p {
margin: 0 0 1.25rem;
color: var(--fg);
}
このデモに固有の消費側 JS はありません(挙動はコントローラが担います)。
これらのスタイルは共通のデザイントークン(ライト/ダーク両対応)を使います。 共通スタイルも一緒にコピーし、ルート要素の data-theme を切り替えればダークになります。
このコンポーネントを動かすために HTML へ記述する data-* 属性です。ルート要素に下の data-controller を付け、その内側に各 target / value / action を配置します。
ルート要素に付与
data-controller="stimeo--smart-sticky-header"
値(Values)
| 名前 | 説明 | 属性 |
|---|---|---|
containerSelector
|
スクロール源のセレクタ。空(既定)ならウィンドウ。 | data-stimeo--smart-sticky-header-container-selector-value |
offset
|
トップからこの px 以内では隠さない。既定 80。 | data-stimeo--smart-sticky-header-offset-value |
tolerance
|
この未満のスクロール差分は無視(ジッタ対策)。既定 4。 | data-stimeo--smart-sticky-header-tolerance-value |
イベント
| 名前 | 説明 | イベント |
|---|---|---|
change
|
表示状態の遷移時のみ { hidden } と共に発火。 |
stimeo--smart-sticky-header:change |
状態フック
ライブラリが操作するのはこれらの ARIA / data 属性、カスタムプロパティだけです。見た目は利用側 CSS がこれらに反応して作ります([aria-selected] / [aria-expanded] / var(--stimeo--…) などのセレクタでフックします)。
| フック | 対象 | 意味 |
|---|---|---|
data-header-hidden |
コントローラ要素 | "true"(退避)/ "false"(表示)。消費側 CSS が translate で画面外へ逃がす。 |