ファーストビュー デザイン 9パターン、コピペで置ける
ファーストビュー デザインとは、ページを開いた最初の一画面全体の置き方のことです。ここでは九つのファーストビューを、貼った場所でそのまま動くHTMLとSCSSで載せました。どれも外部のファイルを一つも読み込まず、動きはCSSだけで組んであります。
自動再生 · タイルを押すとその項目へ · すべて1つのzip
- 01 スプリット製品ヒーロー
- 02 センタースタックバッジヒーロー
- 03 単語ごとに現れる見出し
- 04 グラデーション・グラスヒーロー
- 05 製品ズーム・ホットスポットヒーロー
- 06 数値カウンターヒーロー
- 07 スクロールで畳まれるヒーロー
- 08 スプリットスライダーヒーロー
- 09 ミニマルロゴヒーロー
九つの並びは人気で決めたのではなく、訪問者が最初の一画面で出会う順です。まず左右に分けた定番の構えで製品と言葉を並べ(01)、中央にお知らせを立てて発表を伝え(02)、一文の見出しだけで勝負し(03)、写真がなくても色だけで深みを作り(04)、点で機能を指し示し(05)、数字で規模を証明し(06)、スクロールで本文へ渡る継ぎ目を作り(07)、複数の顔を交互に見せ(08)、最後は何も足さない一枚で静かに閉じます(09)。この九つは動きの見せ方ではなく第一画面の骨格の集まりで、動きだけを集めた以前のヒーローアニメーション9選とは別の軸です。色も角丸も九つ共通の変数にまとめてあるので、自分のブランドの色へ差し替えても骨格は保たれます。
01スプリット製品ヒーロー
左の文案とボタン2つに対して、右の製品カードが三枚、0.12秒ずつずれて下から上がってきます。上がりはループの18%で終わり、下がりは60%から88%までかけて退場するので、代表コマは三枚がそろった場面に選ばれます。24コマのうち22コマが動き、変化面積の合計は11.672%です。
.hs.is-demo .hs__card {
animation-name: hsRise;
animation-duration: $duration;
animation-timing-function: $easing;
animation-iteration-count: infinite;
animation-fill-mode: backwards;
}
.hs.is-demo .hs__card--b { animation-delay: .12s; }
.hs.is-demo .hs__card--a { animation-delay: .24s; }
// 上がりは速く(0〜18%)、下がりは遅く(60〜88%)
@keyframes hsRise {
0% { transform: translateY(var(--rise)); }
18%, 60% { transform: translateY(0); }
88%, 100% { transform: translateY(var(--rise)); }
}
@keyframes hsCue {
0%, 100% { transform: translateY(0); }
20% { transform: translateY(-6px); }
40% { transform: translateY(0); }
60% { transform: translateY(-3px); }
80% { transform: translateY(0); }
}
02センタースタックバッジヒーロー
お知らせのバッジの上を光の帯が一度だけ通り(70%で右の外へ出る)、四つの信頼マークが0.14秒ずつずれて浮いては座ります。帯の巻き戻しはバッジのoverflow: hiddenの外で起きるので、画面には一切見えません。24コマのうち23コマが動いていますが、変化面積の合計は3.342%と控えめです。
.hb.is-demo .hb__tile {
animation-name: hbLift;
animation-duration: $duration;
animation-timing-function: $ease-spring;
animation-iteration-count: infinite;
animation-fill-mode: backwards;
}
.hb.is-demo .hb__mark--2 .hb__tile { animation-delay: .14s; }
.hb.is-demo .hb__mark--3 .hb__tile { animation-delay: .28s; }
.hb.is-demo .hb__mark--4 .hb__tile { animation-delay: .42s; }
@keyframes hbSheen {
0% { transform: translateX(-160%); }
70%, 100% { transform: translateX(320%); }
}
@keyframes hbLift {
0% { transform: translateY(0); }
16%, 46% { transform: translateY(-7px); }
88%, 100% { transform: translateY(0); }
}
03単語ごとに現れる見出し
見出しの各単語が、自分の箱の中を115%下から上がってきます(ずれは0.16秒と0.32秒)。ループ開始から0.55秒、三つ目の単語が立ち上がるころに、要の単語の背後へ蛍光の帯が左からscaleXで満ちていきます。24コマのうち動いているのは16コマと九つで最も少ないのに、平均の強度は131.3と高い部類です。
.hk__word {
position: relative;
z-index: 1;
overflow: hidden;
display: inline-block;
padding-bottom: $sp-1;
margin-bottom: -$sp-1;
vertical-align: bottom;
}
.hk__wi { display: inline-block; }
@keyframes hkRise {
0% { transform: translateY(115%); }
16%, 72% { transform: translateY(0); }
86%, 100% { transform: translateY(115%); }
}
@keyframes hkBand {
0% { transform: scaleX(0); }
12%, 50% { transform: scaleX(1); }
60%, 100% { transform: scaleX(0); }
}
04グラデーション・グラスヒーロー
写真を一枚も使わず、三つの色の塊(radial-gradient)が互いに逆方向へゆっくり流れ、その上に半透明のガラスカードが浮かびます。カードはbackdrop-filter: blur(12px) saturate(140%)で背後の色をにじませ、表面を光が一度だけ斜めに走ります。変化面積の合計は34.261%と九つで最も大きいのに、動きが薄く広く広がるため平均の強度は32.2で最も低くなっています。
.hg__blob--a {
left: -64px;
top: -104px;
background: radial-gradient(circle at 50% 50%, $color, rgba($color, 0) 70%);
}
.hg__card {
position: relative;
z-index: 1;
box-sizing: border-box;
width: 100%;
padding: clamp(12px, 3.2vw, 20px);
border: 1px solid rgba(255, 255, 255, .28);
border-radius: $r-card;
background: rgba(255, 255, 255, .10);
backdrop-filter: blur(12px) saturate(140%);
-webkit-backdrop-filter: blur(12px) saturate(140%);
}
@keyframes hgDriftA {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(34px, 22px); }
}
05製品ズーム・ホットスポットヒーロー
製品の絵がループの52%で1.12倍まで拡大し、88%で元の大きさへ戻る間に、二つの呼び出し点が1.28倍へ膨らみ、輪が2.8倍に広がって消え、弾けた位置に説明の札がsteps(1, end)の一コマで現れます。半透明の重なりを作らないためです。24コマのうち21コマが動き、変化面積の合計は10.967%です。
// 説明の札は一コマで切り替わる — 半透明の幽霊を作らない
.hz.is-demo .hz__note {
visibility: visible;
animation-duration: $duration;
animation-timing-function: steps(1, end);
animation-iteration-count: infinite;
transition: none;
}
.hz.is-demo .hz__spot--1 .hz__note { animation-name: hzNote1; }
.hz.is-demo .hz__spot--2 .hz__note { animation-name: hzNote2; }
@keyframes hzZoom {
0% { transform: scale(1); }
52% { transform: scale(1.12); }
88%, 100% { transform: scale(1); }
}
@keyframes hzBurst1 {
0%, 4% { transform: scale(1); opacity: .9; }
26% { transform: scale(2.8); opacity: 0; }
100% { transform: scale(2.8); opacity: 0; }
}
06数値カウンターヒーロー
数字が、縦に7枚並んだ桁の列をsteps(6, end)で六段回って上がり(窓の高さは1.15em)、止まると各数値の下線が左から満ちて確定を知らせます。窓の中でも後ろの桁は0.08秒遅れて立ち、三つの枠全体でも0.16秒ずつずれます。変化面積の合計は2.145%と九つで最も小さいのに、平均の強度は147.3で最も高い値です。
.hc__strip {
display: block;
transform: translateY($hc-cell * -6); // 七枠の最後 = 確定した数字
}
.hc.is-demo .hc__strip {
animation-name: hcRoll;
animation-duration: $duration;
animation-timing-function: steps(6, end);
animation-iteration-count: infinite;
animation-fill-mode: backwards;
animation-delay: var(--d);
}
@keyframes hcRoll {
0% { transform: translateY(0); }
60% { transform: translateY($hc-cell * -6); }
100% { transform: translateY($hc-cell * -6); }
}
07スクロールで畳まれるヒーロー
スクロールすると、ヒーローはposition: stickyでその場に留まったまま0.86倍へ縮んで角が丸くなり、薄い暗幕がかかり、本文のカードが下から20px持ち上がって覆いかぶさります。進行度はスクロール箱にscroll-timeline-name: --hfscrollと名前を付け、ヒーロー・暗幕・カードの三つがanimation-timeline: --hfscrollで明示的に受け取ります。24コマのうち23コマが動き、変化面積の合計は21.196%です。
// タイムラインには名前を付ける — scroll(nearest) は overflow: hidden の箱も掴む
.hf__scroller {
--h: clamp(148px, 58vh, 176px);
position: relative;
height: var(--h);
overflow-y: auto;
overscroll-behavior: contain;
border-radius: $r-card;
background: $hr-ink;
scroll-timeline-name: --hfscroll;
scroll-timeline-axis: y;
scrollbar-width: none;
&::-webkit-scrollbar { display: none; }
&:focus-visible { outline: 2px solid $color; outline-offset: 2px; }
}
@keyframes hfFold {
from { transform: scale(1); border-radius: 0; }
to { transform: scale(.86); border-radius: $r-card; }
}
@keyframes hfRise {
from { transform: translateY(20px); }
to { transform: translateY(0); }
}
08スプリットスライダーヒーロー
三枚のスライドが同じ格子のマスにgrid-area: 1 / 1で重なっており、文字の面は左から、絵の面は右から、逆方向のclip-pathの払いで現れて次の一枚へ渡します。スライドの交代(z順序)はsteps(1, end)の切替だけなので、二枚が薄く重なる幽霊のコマが生まれません。変化面積の合計は17.644%、一コマあたりの最大は13.065%で、アニメーションの数は15と九つで最も多いです。
.hl__pane--copy { clip-path: inset(0 100% 0 0); }
.hl__pane--art { clip-path: inset(0 0 0 100%); }
@keyframes hlZ {
0%, 33.32% { z-index: 3; }
33.33%, 66.65% { z-index: 2; }
66.66%, 100% { z-index: 1; }
}
@keyframes hlWipeL {
0% { clip-path: inset(0 100% 0 0); }
18%, 66.65% { clip-path: inset(0 0 0 0); }
66.66%, 100% { clip-path: inset(0 100% 0 0); }
}
// 点の塗りは一コマ切替 — 18%・51.33% はコマとコマの間に落ちる
@keyframes hlFill {
0%, 17.99% { transform: scale(0); }
18%, 51.32% { transform: scale(1); }
51.33%, 100% { transform: scale(0); }
}
09ミニマルロゴヒーロー
中央のロゴマークの周りを、二つの輪がscaleの0.58から1.9へ広がりながら薄れて消えます。二つ目の輪は-1秒の遅延で半周期ずれており、静かに置いた状態でも輪は1と1.34の倍率で止まって見えます。変化面積の合計は7.483%、平均の強度は47.9で、アニメーションはこの2つだけです。
.hm__ring {
position: absolute;
inset: 0;
border: 3px solid $color;
border-radius: 50%;
scale: 1;
opacity: .34;
}
.hm__ring--b { scale: 1.34; opacity: .18; }
.hm.is-demo .hm__ring--b { animation-delay: -1s; }
@keyframes hmRing {
0% { scale: .58; opacity: .62; }
88% { scale: 1.9; opacity: 0; }
88.01%, 100% { scale: .58; opacity: 0; }
}
どこで壊れるか — 落とし穴
九つが形になるまで、失敗は四つの形で現れました。
一つ目は07のスクロール駆動です。animation-timeline: scroll(nearest)で書くと、この値はoverflow: hiddenを持つ箱までスクロールポートとして掴んでしまい、進行率がいつまでも0のタイムラインに繋がれて、何も畳まれませんでした。そこでタイムラインにscroll-timeline-name: --hfscrollと名前を付け、使う側の三つの部品がanimation-timeline: --hfscrollでその名前を明示する形に改めました。stickyの余白にも同じ種類の罠があります。親にpadding-bottomを足してもstickyの範囲の外なので効かず、ここでは本文カード自身の高さがその余白になっています。もう一つ、覆いかぶさる暗幕にはpointer-events: noneが要りました。この一行がないと、薄い幕がヒーロー全体のボタンの押下を横取りします。畳みの速度感にも理由が二つあります。緩急を等速(linear)に揃えたのは、速く感じる曲線を挟むとスクロール量と画面の動きが1:1で噛み合わなくなるためで、キーフレームを行き方向だけにしてanimation-fill-mode: bothで端に留めたのは、往復を書くと下端で一度元へ戻る揺り戻しが出るためです。カードの側でも、box-sizingをborder-boxにしないとmin-heightにpaddingが上乗せされて40px長くなり、ちょうど覆う計算が崩れました。上の余白を24pxに開けているのは、スクロール量0で覗くカードの端が、二行目の文字に半分掛かるのではなく空行で切れるようにするためです。
二つ目は08の点です。塗りを0%で始めると、まだ前のスライドが見えているのに点だけが先に移ってしまいました。さらに消す位置の33.33%がスライド交代の境界と同じコマに重なり、三つの点が同時に空になる場面まで生まれました。切り替えを18%と51.33%へ動かして解決しています — 24コマは4.1667%間隔なので、この二つの位置はコマとコマの間に落ち、半分だけ塗れた中間コマができません。18%は払いが終わる位置なので、点は新しいスライドが完全に見えてから塗り替わります。払いそのものもsteps()の外へ出して別のアニメーションに分けてあります。steps()のキーフレームの中ではclip-pathが補間されないためです。
三つ目は03の代表画像です。posterは「直前のコマから一番大きく変わったコマ」なので、変化量の小さい部品はどう調整しても選ばれません。蛍光の帯は単語の登場に変化量で勝てないため、代表コマは単語がそろって立つ場面に固定し、帯が満ちる様子はgifで見せることに決めました。単語同士のずれ0.16秒のおかげで、登場の区間には二つの単語が重なって動き、この場面が必ず一番大きく変わることも実測で確かめています。上がり(0〜16%)は下がり(72〜86%)より長く、一コマあたりの変化はむしろ小さいので、ずらして重ねる以外に勝ち方はありません。
四つ目は二つの小さな穴です。06の桁の列は、静的な規則で最初からtranslateY($hc-cell * -6)(七枠の最後、つまり確定した数字)にピン留めしておかないと、.is-demoを外した瞬間に窓が空っぽになります。04では、明るい色の塊が文字の後ろに回り込んでミスト色の補助文案のコントラストを食いました。塊の二つを下へ下げて(bottom: -136pxは右下の隅、-160pxは下の右寄り)、文字が座る左上を空けています。九つ分のSCSSとReact版、そしてここまでの切り替えをまとめた一式は、u6yhwkzqを入れて開くzipにそのまま入っています。
アクセシビリティ
九つの第一画面は四つの土台(クリーム・イエロー・インク・オレンジ)の上に組んであり、文字と背景の組み合わせを WCAG 2.1 の相対輝度式で一つひとつ測った結果が次の表です。下の三行は基準に足りなかったので、本文では使っていません。
| 前景 | 背景 | 実測コントラスト | 判定 |
|---|---|---|---|
| 白 #ffffff | インク #17141a | 18.24:1 | 合格 |
| イエロー #ffd23f | インク #17141a | 12.63:1 | 合格 |
| ライラック #9d93ff | インク #17141a | 6.99:1 | 合格 |
| ミスト #b6b0c0 | インク #17141a | 8.65:1 | 合格 |
| インク #17141a | クリーム #fdf7ec | 17.10:1 | 合格 |
| ストーン #56505e | クリーム #fdf7ec | 7.28:1 | 合格 |
| バイオレット #5b4bd6 | クリーム #fdf7ec | 5.75:1 | 合格 |
| 白 #ffffff | バイオレット #5b4bd6 | 6.14:1 | 合格 |
| 白 #ffffff | グラス #0f7a52 | 5.35:1 | 合格 |
| 白 #ffffff | オレンジ #ff4d1f | 3.32:1 | 不足 — 使わない |
| 白 #ffffff | イエロー #ffd23f | 1.44:1 | 不足 — 使わない |
| バイオレット #5b4bd6 | インク #17141a | 2.97:1 | 不足 — 使わない |
prefers-reduced-motion: reduceの環境では、九つとも装飾の動きだけを止めて、値と状態は手元に残ります。01はカードの上昇と案内の跳ねが止まっても三枚のカードと文案がそのまま見え、02は光の帯を消してもバッジと四つのマークが残ります。03は単語が最初から並んだ状態で立ち、蛍光の帯は満ちたままです。04は色の塊と光が止まってもガラスカードの文字は動かず、右上の停止スイッチ(aria-pressed)は引き続き機能します。05は拡大と輪を止めたうえで説明の札をopacity: 1に戻すので、二つの機能の説明が欠けません。06は桁の列が最初から確定位置にいるので数値とラベルがそのまま読め、07は畳みを切っても直立したヒーローと本文カードが残ります。08は今の枚だけが全面的に見え、点もaria-currentのある一つだけが塗られたままです。09は輪が静かな位置で止まり、登録の受け付けはrole="status"でそっと読み上げられます。
骨格の側も揃えてあります。第一画面の大見出しは高々一つ(08だけはスライドごとのh2で、09は見出しを持たない一枚です)で、読み上げは見出しから文案、ボタン、補助の順に流れます。キーボードで触れる要素にはすべて:focus-visibleの輪郭を付け、05の呼び出し点はaria-expandedとaria-controls、08の点はaria-current、04と09のスイッチはaria-pressedで状態を伝えます。06の回転する数値は、窓の中の桁をaria-hiddenに隠して値をaria-label一つで読ませ、07のスクロール箱はrole="region"に名前を付けてTabで入れるようにしました。根拠はMDN の scroll-timeline-nameとMDN の backdrop-filter、コントラストの基準はW3C の Understanding Contrast (Minimum)です。
第一画面の骨格をさらに見るならヒーロー枠の一覧に並べてあります。運営している人のことはサイト紹介に書いてあります。
FAQ
写真を一枚も用意できません。使えるパターンはありますか
04・08・09は写真なしで成立します。実際には九つすべて、画像ファイルを一つも読み込みません。絵はCSSの図形とインラインのSVGだけで描いてあるので、差し替えの前から見た目が完結しています。
07はFirefoxやSafariでも畳まれますか
Safari 26 は畳まれますが、Firefox はまだです(2026年9月の実測でanimation-timelineは Chrome・Edge 115以降と Safari 26 が対応、世界の87.22%)。実装していないブラウザでは、ヒーローは直立したまま本文カードが上を通過します。静的な規則を先に書いてあるので、崩れた画面にはなりません。
文言と数字はどこで差し替えますか
文案はHTMLの本文を、数字は06の桁の列をそのまま書き換えます。色は各style.scssの先頭にある数行の変数($hr-*と$color)で、速さは$durationの一行です。React版も同じ三つ(時間・緩急・色)をpropsで受け取ります。