スクロール表示切替
stimeo--scroll-visibility
スクロールの量や向きに応じて要素を出し入れします。「トップへ戻る」や隠れるヘッダに使えます。
スクロールに応じて要素を出し入れします。使い方は 2 通りで、ある高さより下へ来たら出す形と、下へ動いている間は隠して上へ動かすと出す形があります。「トップへ戻る」ボタンや、読んでいる間だけ引っ込むヘッダに向いています。ふつうはページ全体のスクロールを見ますが、ページ自体は動かず中の枠だけが動くつくりのときは、その枠を見るように指定できます。隠している間は Tab の順番からも外れるので、見えないボタンにフォーカスが入りません。先頭へ戻る動きは、動きを減らす設定の人には一瞬で行います。
この枠の中を下へスクロールすると、右下に「トップへ戻る」ボタンが現れます。
コンテンツ行 1
コンテンツ行 2
コンテンツ行 3
コンテンツ行 4
コンテンツ行 5
コンテンツ行 6
コンテンツ行 7
コンテンツ行 8
コンテンツ行 9
コンテンツ行 10
コンテンツ行 11
コンテンツ行 12
キーボード操作
| キー | 動作 |
|---|---|
| Enter / Space | 「トップへ戻る」ボタンを実行(標準ボタン挙動)。 |
<%# Markup for the scroll-visibility (scroll-driven visibility toggle / GoToTop) demo.
The library toggles the target via hidden / data-state once the scroll source passes a
threshold, and toTop scrolls that source back to the top. Here the scroll source is the
demo's own scroll box (root points at it), so the demo is self-contained and works even
when the page itself does not scroll on the window. The look and transition are demo.css's.
Scroll inside the box and a "Back to top" button appears at the bottom-right. %>
<div
class="scroll-visibility-demo"
data-controller="stimeo--scroll-visibility"
data-stimeo--scroll-visibility-root-value="#scroll-visibility-demo-scroller"
data-stimeo--scroll-visibility-offset-value="120"
data-stimeo--scroll-visibility-mode-value="offset">
<div id="scroll-visibility-demo-scroller" class="scroll-visibility-demo__scroller"
tabindex="0" role="region" aria-labelledby="scroll-visibility-demo-hint">
<p id="scroll-visibility-demo-hint" class="scroll-visibility-demo__hint"><%= t(
"components.scroll_visibility.demo.hint"
) %></p>
<% 12.times do |i| %>
<p class="scroll-visibility-demo__line"><%= t(
"components.scroll_visibility.demo.line", number: i + 1
) %></p>
<% end %>
</div>
<button
type="button"
class="go-to-top"
hidden
data-stimeo--scroll-visibility-target="element"
data-action="click->stimeo--scroll-visibility#toTop">
<%= t("components.scroll_visibility.demo.to_top") %>
</button>
</div>
/* Presentation CSS for scroll-visibility. The library only toggles hidden / data-state
and does the toTop scroll, so visuals like the scroll box, positioning, and fade are
drawn here. The demo scrolls inside its own box (the controller's root) rather than the
window, so the "Back to top" button is pinned to the box, not the viewport. */
.scroll-visibility-demo {
position: relative; /* positioning context for the absolutely-pinned button */
color: var(--color-text-muted);
}
/* The scroll source the controller observes (data-...-root-value points here). */
.scroll-visibility-demo__scroller {
max-height: 16rem;
overflow-y: auto;
padding: 1rem;
border: 1px solid var(--border-default);
border-radius: 0.5rem;
background: var(--surface-subtle);
}
.scroll-visibility-demo__scroller:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
.scroll-visibility-demo__hint {
margin: 0 0 0.5rem;
font-weight: 600;
}
.scroll-visibility-demo__line {
margin: 0.5rem 0;
}
/* "Back to top" button, pinned to the demo box. Visible only once the library removes
hidden (and the control is back in the focus order). */
.go-to-top {
position: absolute;
right: 1.25rem;
bottom: 1.25rem;
z-index: 1;
padding: 0.6rem 1rem;
border: none;
border-radius: 999px;
background: var(--color-primary-hover);
color: var(--white);
font-weight: 600;
cursor: pointer;
box-shadow: 0 6px 16px rgba(var(--vital-rgb), 0.4);
transition: opacity 0.2s ease, transform 0.2s ease;
}
.go-to-top:hover {
transform: translateY(-2px);
}
.go-to-top:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
.go-to-top {
transition: none;
}
.go-to-top:hover {
transform: none;
}
}
このデモに固有の消費側 JS はありません(挙動はコントローラが担います)。
これらのスタイルは共通のデザイントークン(ライト/ダーク両対応)を使います。共通スタイルも一緒にコピーし、ルート要素の data-theme を切り替えればダークになります。
このコンポーネントを動かすために HTML へ記述する data-* 属性です。ルート要素に下の data-controller を付け、その内側に各 target / value / action を配置します。
ルート要素に付与
data-controller="stimeo--scroll-visibility"
ターゲット
| 名前 | 説明 | 属性 |
|---|---|---|
element
必須
|
スクロールに応じてhidden/data-stateで表示・非表示される要素。 |
data-stimeo--scroll-visibility-target="element" |
値(Values)
| 名前 | 説明 | 属性 |
|---|---|---|
offset
|
表示判定のスクロール量(offsetモード)または上部の常時表示域(directionモード)。既定400。 | data-stimeo--scroll-visibility-offset-value |
mode
|
表示ロジック。offset(offset超で表示)かdirection(上スクロールで表示)。既定offset。 |
data-stimeo--scroll-visibility-mode-value |
focusSelector
|
toTop後にフォーカスを移す任意のセレクター(既定は空)。 |
data-stimeo--scroll-visibility-focus-selector-value |
root
|
スクロール元コンテナの任意セレクター。既定はwindow。 | data-stimeo--scroll-visibility-root-value |
アクション
| 名前 | 説明 | アクション |
|---|---|---|
toTop
|
スクロール元を最上部へ戻し、任意でfocusSelectorへフォーカスを移す(reduced motion尊重)。 |
stimeo--scroll-visibility#toTop |
イベント
| 名前 | 説明 | イベント |
|---|---|---|
change
|
表示状態が変わると発火する。detailにvisibleの真偽値を含む。 | stimeo--scroll-visibility:change |
状態フック
ライブラリが操作するのはこれらの ARIA / data 属性、カスタムプロパティだけです。見た目は利用側 CSS がこれらに反応して作ります([aria-selected] / [aria-expanded] / var(--stimeo--…) などのセレクタでフックします)。
| フック | 対象 | 意味 |
|---|---|---|
hidden |
対象要素 | しきい値未満で非表示(フォーカス順からも除外)。 |
data-state |
ルート要素 | "hidden" / "visible"。 |