01배경 느리게 이동
배경 하나만 스크롤 속도보다 느리게 움직여 앞의 글자와 사이가 벌어지며 깊이가 생긴다.
쓰임랜딩 히어로 배경, 섹션 상단 배너
0.4배translateY단일 레이어

<main class="stage is-demo">
<div class="bgslow">
<div class="bgslow__bg" aria-hidden="true"></div>
<h2 class="bgslow__title">배경만 느리게</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 배경 느리게 이동 — 측정 누적면적 3.371% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · CSS 패럴랙스 스크롤 9종 — AOS·GSAP 없이, JS 0줄
이 데모가 속한 글
CSS 패럴랙스 스크롤 9종 — AOS·GSAP 없이, JS 0줄CSS 패럴랙스 스크롤 아홉 개를 모았습니다. 레이어마다 이동 속도를 다르게 주는 원리 하나로 배경이 내용보다 느리게 움직이는 착시를 만듭니다. 격자에서는 아홉 개가 2초 간격으로 자동 반복되니 먼저 눈으로 훑고 마 이 글의 데모 전부 보기


