|
| 1 | +<!DOCTYPE html> |
| 2 | +<html lang="ja"> |
| 3 | +<head> |
| 4 | +<meta charset="UTF-8" /> |
| 5 | +<meta name="viewport" content="width=device-width,initial-scale=1" /> |
| 6 | +<title>Tech Dark Background</title> |
| 7 | +<style> |
| 8 | +:root{ |
| 9 | + --color-bg-0:#000; |
| 10 | + --color-bg-1:#232323; |
| 11 | + --color-bg-2:#875e46; |
| 12 | + --color-text-0:#d1d1d1; |
| 13 | + --color-text-1:#fff; |
| 14 | + --color-accent-0:#815a44; |
| 15 | + --color-accent-1:#e8af7f; |
| 16 | + |
| 17 | + /* スクロール→JS で更新されるオフセット(px) */ |
| 18 | + --scrollOffset:0px; |
| 19 | +} |
| 20 | + |
| 21 | +/* -------------------------------- ベース */ |
| 22 | +html{background:#000;margin:0;padding:0;} |
| 23 | + |
| 24 | +.backwapper{ |
| 25 | + position:fixed; |
| 26 | + inset:0; |
| 27 | + z-index:-999; |
| 28 | + overflow:hidden; |
| 29 | + |
| 30 | + /* ── グリッド/ドット/右下グラデーション ───────── */ |
| 31 | + background: |
| 32 | + linear-gradient(color-mix(in srgb,var(--color-accent-0) 10%,transparent) 1px,transparent 1px), |
| 33 | + linear-gradient(90deg,color-mix(in srgb,var(--color-accent-0) 10%,transparent) 1px,transparent 1px), |
| 34 | + radial-gradient(circle at 0 0,var(--color-accent-1) 1px,transparent 1px), |
| 35 | + radial-gradient(ellipse at bottom right, |
| 36 | + color-mix(in srgb,var(--color-accent-0) 30%,transparent) 0%, |
| 37 | + var(--color-bg-0) 60%); |
| 38 | + background-size:40px 40px,40px 40px,80px 80px,100% 100%; |
| 39 | + |
| 40 | + /* ▼ここが “スクロール × 0.3” で常に変わる */ |
| 41 | + background-position: |
| 42 | + 0 calc(-1 * var(--scrollOffset)), |
| 43 | + 0 calc(-1 * var(--scrollOffset)), |
| 44 | + 0 calc(-1 * var(--scrollOffset)), |
| 45 | + 0 0; |
| 46 | + |
| 47 | + /* ── 200 ms で滑らかに補間させる ─────────────── */ |
| 48 | + transition:background-position 1000ms ease-out; |
| 49 | + will-change:background-position; |
| 50 | + |
| 51 | + /* ── マスク(光が走るアニメ) ────────────── */ |
| 52 | + mask-image:repeating-linear-gradient( |
| 53 | + 120deg, |
| 54 | + transparent 0%, transparent 8%, |
| 55 | + color-mix(in srgb,var(--color-bg-0) 20%,transparent) 12%, |
| 56 | + color-mix(in srgb,var(--color-bg-0) 50%,transparent) 16%, |
| 57 | + color-mix(in srgb,var(--color-bg-0) 80%,transparent) 20%, |
| 58 | + black 24%, black 36%, |
| 59 | + color-mix(in srgb,var(--color-bg-0) 80%,transparent) 40%, |
| 60 | + color-mix(in srgb,var(--color-bg-0) 50%,transparent) 44%, |
| 61 | + color-mix(in srgb,var(--color-bg-0) 20%,transparent) 48%, |
| 62 | + transparent 52%, transparent 58%, |
| 63 | + color-mix(in srgb,var(--color-bg-0) 20%,transparent) 62%, |
| 64 | + color-mix(in srgb,var(--color-bg-0) 50%,transparent) 66%, |
| 65 | + color-mix(in srgb,var(--color-bg-0) 80%,transparent) 70%, |
| 66 | + black 74%, black 86%, |
| 67 | + color-mix(in srgb,var(--color-bg-0) 80%,transparent) 90%, |
| 68 | + color-mix(in srgb,var(--color-bg-0) 50%,transparent) 94%, |
| 69 | + color-mix(in srgb,var(--color-bg-0) 20%,transparent) 98%, |
| 70 | + transparent 100% |
| 71 | + ); |
| 72 | + -webkit-mask-image:repeating-linear-gradient(120deg,transparent 0%,transparent 8%,color-mix(in srgb,var(--color-bg-0) 20%,transparent) 12%,color-mix(in srgb,var(--color-bg-0) 50%,transparent) 16%,color-mix(in srgb,var(--color-bg-0) 80%,transparent) 20%,black 24%,black 36%,color-mix(in srgb,var(--color-bg-0) 80%,transparent) 40%,color-mix(in srgb,var(--color-bg-0) 50%,transparent) 44%,color-mix(in srgb,var(--color-bg-0) 20%,transparent) 48%,transparent 52%,transparent 58%,color-mix(in srgb,var(--color-bg-0) 20%,transparent) 62%,color-mix(in srgb,var(--color-bg-0) 50%,transparent) 66%,color-mix(in srgb,var(--color-bg-0) 80%,transparent) 70%,black 74%,black 86%,color-mix(in srgb,var(--color-bg-0) 80%,transparent) 90%,color-mix(in srgb,var(--color-bg-0) 50%,transparent) 94%,color-mix(in srgb,var(--color-bg-0) 20%,transparent) 98%,transparent 100%); |
| 73 | + mask-size:200% 200%; |
| 74 | + mask-repeat:no-repeat; |
| 75 | + animation:flowMask 12s linear infinite; |
| 76 | +} |
| 77 | + |
| 78 | +@keyframes flowMask{ |
| 79 | + 0% {mask-position:0% 0%;} |
| 80 | + 100% {mask-position:100% 100%;} |
| 81 | +} |
| 82 | + |
| 83 | +/* ---------- DEMO 用本文 ---------- */ |
| 84 | +main{ |
| 85 | + max-width:54rem; |
| 86 | + margin:auto; |
| 87 | + padding:8rem 2rem; |
| 88 | + line-height:1.7; |
| 89 | + color:var(--color-text-0); |
| 90 | + font-family:system-ui,Helvetica,Arial,sans-serif; |
| 91 | +} |
| 92 | +p{margin:0 0 2rem;} |
| 93 | +</style> |
| 94 | +</head> |
| 95 | +<body> |
| 96 | + |
| 97 | +<div class="backwapper"></div> |
| 98 | + |
| 99 | +<main> |
| 100 | + <h1>スクロールテスト</h1> |
| 101 | + <p>ページをスクロールすると、グリッドが 0.3× の速度で、200 ms の滑らかさで追従します。</p> |
| 102 | + <script> |
| 103 | + for(let i=0;i<120;i++){ |
| 104 | + document.write(`<p>ダミーテキスト ${i+1}</p>`); |
| 105 | + } |
| 106 | + </script> |
| 107 | +</main> |
| 108 | + |
| 109 | +<script> |
| 110 | +/* ===================================================== |
| 111 | + スクロール基準を「読み込み時の位置 = 0」にする版 |
| 112 | + ===================================================== */ |
| 113 | +const root = document.documentElement; |
| 114 | +const baseScroll = root.scrollTop || window.scrollY; // ←★ ここが基準 |
| 115 | + |
| 116 | +let ticking = false; |
| 117 | + |
| 118 | +/* rAF で 1 frame に 1 回だけ更新 */ |
| 119 | +function sync(){ |
| 120 | + const current = root.scrollTop || window.scrollY; |
| 121 | + const offsetPx = (current - baseScroll) * 0.1; // ← 差分 × 0.3 |
| 122 | + root.style.setProperty('--scrollOffset', offsetPx.toFixed(1)+'px'); |
| 123 | + ticking = false; |
| 124 | +} |
| 125 | + |
| 126 | +addEventListener('scroll', ()=>{ |
| 127 | + if(!ticking){ requestAnimationFrame(sync); ticking = true; } |
| 128 | +},{passive:true}); |
| 129 | + |
| 130 | +sync(); // 初期描画(ページを開いた時点の位置 = 0) |
| 131 | +</script> |
| 132 | + |
| 133 | + |
| 134 | +</body> |
| 135 | +</html> |
0 commit comments