01Slow-moving background
A single background layer moves slower than the scroll itself, opening a gap that reads as depth.
Best forLanding hero backgrounds, section-top banners
0.4배translateY단일 레이어

<main class="stage is-demo">
<div class="bgslow">
<div class="bgslow__bg" aria-hidden="true"></div>
<h2 class="bgslow__title">Only the background slows down</h2>
</div>
</main>@use "../../../../site/static/demo-tokens" as *;
// ── 변수 3개. 변형은 이것만 바꾼다 (값은 토큰에서 받는다) ──────
$shift: 24px; // 배경 이동량 (스크롤의 0.4배 느낌)
$duration: $dur-loop; // 데모 왕복 주기
$color: $subject-cream; // 배경 점 색 (ink 무대라 cream)
@include stage($stage-ink);
.bgslow {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
display: grid;
place-items: center;
&__bg {
position: absolute;
inset: -20% -10%;
background:
radial-gradient($color 0 46px, transparent 47px) 24% 30%,
radial-gradient($color 0 30px, transparent 31px) 78% 62%,
radial-gradient($color 0 20px, transparent 21px) 55% 82%;
background-repeat: no-repeat;
opacity: .5;
// ── 실제 사용 코드: 배경 하나만 스크롤보다 느리게(0.4배) 움직인다 ──
@supports (animation-timeline: scroll()) {
animation: drift linear both;
animation-timeline: scroll(root);
}
@supports not (animation-timeline: scroll()) {
transform: none;
}
}
&__title {
position: relative;
z-index: 1;
margin: 0;
padding: 14px 22px;
border-radius: $r-pill;
background: $subject-blue;
color: #fff;
font: 700 clamp(15px, 5vw, 19px)/1 -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
}
}
@keyframes drift { from { transform: translateY(0); } to { transform: translateY(-#{$shift}); } }
// ── 데모(.is-demo): 스크롤 대신 왕복 루프로 흉내 ────────
.stage.is-demo .bgslow__bg {
animation: drift-loop $duration ease-in-out infinite;
}
@keyframes drift-loop {
0%, 100% { transform: translateY($shift); }
50% { transform: translateY(-$shift); }
}
// ── 접근성: 움직임 줄이기 설정이면 배경을 그대로 고정 ────────────
@media (prefers-reduced-motion: reduce) {
.bgslow__bg, .stage.is-demo .bgslow__bg { animation: none !important; transform: none; }
}html, body {
margin: 0;
overflow: hidden;
}
.stage {
box-sizing: border-box;
min-height: 100vh;
display: grid;
place-items: center;
margin: 0;
background: #17141a;
font-family: -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
padding: clamp(8px, 4vw, 24px);
}
.bgslow {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
display: grid;
place-items: center;
}
.bgslow__bg {
position: absolute;
inset: -20% -10%;
background: radial-gradient(#fff7e6 0 46px, transparent 47px) 24% 30%, radial-gradient(#fff7e6 0 30px, transparent 31px) 78% 62%, radial-gradient(#fff7e6 0 20px, transparent 21px) 55% 82%;
background-repeat: no-repeat;
opacity: 0.5;
}
@supports (animation-timeline: scroll()) {
.bgslow__bg {
animation: drift linear both;
animation-timeline: scroll(root);
}
}
@supports not (animation-timeline: scroll()) {
.bgslow__bg {
transform: none;
}
}
.bgslow__title {
position: relative;
z-index: 1;
margin: 0;
padding: 14px 22px;
border-radius: 999px;
background: #2f6df6;
color: #fff;
font: 700 clamp(15px, 5vw, 19px)/1 -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
}
@keyframes drift {
from {
transform: translateY(0);
}
to {
transform: translateY(-24px);
}
}
.stage.is-demo .bgslow__bg {
animation: drift-loop 2s ease-in-out infinite;
}
@keyframes drift-loop {
0%, 100% {
transform: translateY(24px);
}
50% {
transform: translateY(-24px);
}
}
@media (prefers-reduced-motion: reduce) {
.bgslow__bg, .stage.is-demo .bgslow__bg {
animation: none !important;
transform: none;
}
}import type { CSSProperties, ReactNode } from "react";
import styles from "./SlowBackground.module.scss";
export type SlowBackgroundProps = {
children: ReactNode;
/** 배경 이동량 (기본 24px, 스크롤의 0.4배 느낌) */
shift?: number;
/** 배경 점 색 */
color?: string;
className?: string;
};
type Vars = CSSProperties & { "--shift"?: string; "--color"?: string };
export default function SlowBackground({
children,
shift = 24,
color = "#fff7e6",
className = "",
}: SlowBackgroundProps) {
const vars: Vars = { "--shift": `${shift}px`, "--color": color };
return (
<div className={`${styles.wrap} ${className}`} style={vars}>
<div className={styles.bg} aria-hidden="true" />
<div className={styles.title}>{children}</div>
</div>
);
}01 Slow-moving background — Measured area 3.371% · moving frames 23/23Original by GODRICH · SCSS and React ship in the zip · 9 CSS Parallax Scrolling — No JS, Scroll-Driven
The post this demo lives in
9 CSS Parallax Scrolling — No JS, Scroll-DrivenCSS parallax scrolling is scroll-linked motion — a background, a layer, a whole hero — driven entirely by animation-time See all demos in this post


