03색종이 머리띠 카드 격자
흰 카드 세 장의 윗머리에 서로 다른 색종이 띠를 하나씩 얹고, 0.22초씩 어긋난 차례로 카드가 들렸다 내려앉습니다.
쓰임기능 소개 3열 카드, 포트폴리오 격자
시차 0.22s머리띠 색종이radius 16

<main class="stage">
<section class="cardpaper">
<article class="cardpaper__card cardpaper__card--coral">
<span class="cardpaper__ic" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><g fill="currentColor"><path d="m224 80l-96 56l-96-56l96-56Z" opacity=".2"/><path d="M230.91 172a8 8 0 0 1-2.91 10.91l-96 56a8 8 0 0 1-8.06 0l-96-56A8 8 0 0 1 36 169.09l92 53.65l92-53.65a8 8 0 0 1 10.91 2.91M220 121.09l-92 53.65l-92-53.65a8 8 0 0 0-8 13.82l96 56a8 8 0 0 0 8.06 0l96-56a8 8 0 1 0-8.06-13.82M24 80a8 8 0 0 1 4-6.91l96-56a8 8 0 0 1 8.06 0l96 56a8 8 0 0 1 0 13.82l-96 56a8 8 0 0 1-8.06 0l-96-56A8 8 0 0 1 24 80m23.88 0L128 126.74L208.12 80L128 33.26Z"/></g></svg>
</span>
<h2 class="cardpaper__t">겹치기</h2>
<p class="cardpaper__d">깊이는 층으로</p>
</article>
<article class="cardpaper__card cardpaper__card--sky">
<span class="cardpaper__ic" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><g fill="currentColor"><path d="M224 32c0 32.81-31.64 67.43-58.64 91.05A84.4 84.4 0 0 0 133 90.64c23.57-27 58.19-58.64 91-58.64" opacity=".2"/><path d="M232 32a8 8 0 0 0-8-8c-44.08 0-89.31 49.71-114.43 82.63A60 60 0 0 0 32 164c0 30.88-19.54 44.73-20.47 45.37A8 8 0 0 0 16 224h76a60 60 0 0 0 57.37-77.57C182.3 121.31 232 76.08 232 32M92 208H34.63C41.38 198.41 48 183.92 48 164a44 44 0 1 1 44 44m32.42-94.45q5.14-6.66 10.09-12.55A76.2 76.2 0 0 1 155 121.49q-5.9 4.94-12.55 10.09a60.5 60.5 0 0 0-18.03-18.03m42.7-2.68a92.6 92.6 0 0 0-22-22c31.78-34.53 55.75-45 69.9-47.91c-2.85 14.16-13.37 38.13-47.9 69.91"/></g></svg>
</span>
<h2 class="cardpaper__t">칠하기</h2>
<p class="cardpaper__d">색은 세 가지만</p>
</article>
<article class="cardpaper__card cardpaper__card--leaf">
<span class="cardpaper__ic" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg>
</span>
<h2 class="cardpaper__t">붙이기</h2>
<p class="cardpaper__d">그림자로 고정</p>
</article>
</section>
</main>@use "../../../../site/static/demo-tokens" as *;
// 페이퍼컷 팔레트
$paper-base: #fbf6ec;
$paper-sheet: #ffffff;
$paper-ink: #2a2320;
$paper-stone: #5c5048;
$paper-coral: #b97b71;
$paper-sky: #6a8db5;
$paper-leaf: #2b7d5a;
$paper-butter: #d6c9ab;
$paper-edge: #e7dccb;
$duration: $dur-loop; // 카드 한 장이 들렸다 앉는 주기. 셋은 같은 주기를 시차로 나눠 쓴다
$easing: $ease-spring; // 위로 뜰 때만 살짝 탄력
$color: $paper-sheet; // 카드 본체는 흰 종이, 색은 머리띠에만
@include stage($paper-butter);
.cardpaper {
display: flex;
gap: $sp-3;
align-items: stretch; // 세 장의 높이를 맞춘다. flex-end 로 두면 글 길이만큼 아랫단이 어긋난다
}
.cardpaper__card {
box-sizing: border-box;
position: relative;
width: 120px;
padding: $sp-6 $sp-3 $sp-4;
border-radius: $r-card;
background: $color;
box-shadow: 0 6px 0 rgba($paper-ink, .16);
animation: cardPeel $duration $easing infinite;
}
// 카드 위 오려 붙인 머리띠 — 카드마다 다른 색종이
.cardpaper__card::before {
content: "";
position: absolute;
left: $sp-3;
right: $sp-3;
top: -8px;
height: $sp-4;
border-radius: $r-xs;
}
.cardpaper__card--coral::before { background: $paper-coral; }
.cardpaper__card--sky::before { background: $paper-sky; }
.cardpaper__card--leaf::before { background: $paper-leaf; }
.cardpaper__card--sky { animation-delay: -.22s; }
.cardpaper__card--leaf { animation-delay: -.44s; }
.cardpaper__ic {
display: block;
font-size: 26px;
line-height: 1;
margin-bottom: $sp-2;
}
.cardpaper__card--coral .cardpaper__ic { color: $paper-coral; }
.cardpaper__card--sky .cardpaper__ic { color: $paper-sky; }
.cardpaper__card--leaf .cardpaper__ic { color: $paper-leaf; }
.cardpaper__t {
margin: 0 0 $sp-1;
color: $paper-ink;
font-weight: 800; font-size: 15px; line-height: 1.2;
font-family: inherit;
}
.cardpaper__d {
margin: 0;
color: $paper-stone;
font-weight: 500; font-size: 12px; line-height: 1.35;
font-family: inherit;
}
// 데모: 세 장이 0.22초씩 어긋나 차례로 들린다 — 겹쳐 붙인 종이가 한 장씩 떨어지는 것처럼
@keyframes cardPeel {
0%, 100% { transform: translateY(0) rotate(0deg); box-shadow: 0 6px 0 rgba($paper-ink, .16); }
45% { transform: translateY(-14px) rotate(-2deg); box-shadow: 0 18px 8px rgba($paper-ink, .12); }
}
@media (max-width: 340px), (max-height: 220px) {
.cardpaper { gap: $sp-2; }
.cardpaper__card { width: 84px; padding: $sp-5 $sp-2 $sp-3; }
.cardpaper__ic { font-size: 20px; margin-bottom: $sp-1; }
.cardpaper__t { font-size: 13px; }
.cardpaper__d { display: none; }
}
@media (prefers-reduced-motion: reduce) {
.cardpaper__card { 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: #d6c9ab;
font-family: -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
padding: clamp(8px, 4vw, 24px);
}
.cardpaper {
display: flex;
gap: 12px;
align-items: stretch;
}
.cardpaper__card {
box-sizing: border-box;
position: relative;
width: 120px;
padding: 24px 12px 16px;
border-radius: 16px;
background: #ffffff;
box-shadow: 0 6px 0 rgba(42, 35, 32, 0.16);
animation: cardPeel 2s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.cardpaper__card::before {
content: "";
position: absolute;
left: 12px;
right: 12px;
top: -8px;
height: 16px;
border-radius: 4px;
}
.cardpaper__card--coral::before {
background: #b97b71;
}
.cardpaper__card--sky::before {
background: #6a8db5;
}
.cardpaper__card--leaf::before {
background: #2b7d5a;
}
.cardpaper__card--sky {
animation-delay: -0.22s;
}
.cardpaper__card--leaf {
animation-delay: -0.44s;
}
.cardpaper__ic {
display: block;
font-size: 26px;
line-height: 1;
margin-bottom: 8px;
}
.cardpaper__card--coral .cardpaper__ic {
color: #b97b71;
}
.cardpaper__card--sky .cardpaper__ic {
color: #6a8db5;
}
.cardpaper__card--leaf .cardpaper__ic {
color: #2b7d5a;
}
.cardpaper__t {
margin: 0 0 4px;
color: #2a2320;
font-weight: 800;
font-size: 15px;
line-height: 1.2;
font-family: inherit;
}
.cardpaper__d {
margin: 0;
color: #5c5048;
font-weight: 500;
font-size: 12px;
line-height: 1.35;
font-family: inherit;
}
@keyframes cardPeel {
0%, 100% {
transform: translateY(0) rotate(0deg);
box-shadow: 0 6px 0 rgba(42, 35, 32, 0.16);
}
45% {
transform: translateY(-14px) rotate(-2deg);
box-shadow: 0 18px 8px rgba(42, 35, 32, 0.12);
}
}
@media (max-width: 340px), (max-height: 220px) {
.cardpaper {
gap: 8px;
}
.cardpaper__card {
width: 84px;
padding: 20px 8px 12px;
}
.cardpaper__ic {
font-size: 20px;
margin-bottom: 4px;
}
.cardpaper__t {
font-size: 13px;
}
.cardpaper__d {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.cardpaper__card {
animation: none !important;
transform: none;
}
}import type { CSSProperties, ReactNode } from "react";
import styles from "./CardGridPaper.module.scss";
export type PaperCard = { title: string; desc: string; band: "coral" | "sky" | "leaf"; icon: "stack" | "brush" | "sparkle" };
export type CardGridPaperProps = {
cards?: PaperCard[];
/** 한 주기(기본 2000ms) */
duration?: number;
easing?: string;
/** 카드 한 장이 늦게 들리는 간격(ms) */
stagger?: number;
};
type Vars = CSSProperties & { "--duration"?: string; "--easing"?: string; "--delay"?: string };
const ICON: Record<PaperCard["icon"], ReactNode> = {
stack: <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><g fill="currentColor"><path d="m224 80l-96 56l-96-56l96-56Z" opacity=".2"/><path d="M230.91 172a8 8 0 0 1-2.91 10.91l-96 56a8 8 0 0 1-8.06 0l-96-56A8 8 0 0 1 36 169.09l92 53.65l92-53.65a8 8 0 0 1 10.91 2.91M220 121.09l-92 53.65l-92-53.65a8 8 0 0 0-8 13.82l96 56a8 8 0 0 0 8.06 0l96-56a8 8 0 1 0-8.06-13.82M24 80a8 8 0 0 1 4-6.91l96-56a8 8 0 0 1 8.06 0l96 56a8 8 0 0 1 0 13.82l-96 56a8 8 0 0 1-8.06 0l-96-56A8 8 0 0 1 24 80m23.88 0L128 126.74L208.12 80L128 33.26Z"/></g></svg>,
brush: <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><g fill="currentColor"><path d="M224 32c0 32.81-31.64 67.43-58.64 91.05A84.4 84.4 0 0 0 133 90.64c23.57-27 58.19-58.64 91-58.64" opacity=".2"/><path d="M232 32a8 8 0 0 0-8-8c-44.08 0-89.31 49.71-114.43 82.63A60 60 0 0 0 32 164c0 30.88-19.54 44.73-20.47 45.37A8 8 0 0 0 16 224h76a60 60 0 0 0 57.37-77.57C182.3 121.31 232 76.08 232 32M92 208H34.63C41.38 198.41 48 183.92 48 164a44 44 0 1 1 44 44m32.42-94.45q5.14-6.66 10.09-12.55A76.2 76.2 0 0 1 155 121.49q-5.9 4.94-12.55 10.09a60.5 60.5 0 0 0-18.03-18.03m42.7-2.68a92.6 92.6 0 0 0-22-22c31.78-34.53 55.75-45 69.9-47.91c-2.85 14.16-13.37 38.13-47.9 69.91"/></g></svg>,
sparkle: <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg>,
};
const BAND: Record<PaperCard["band"], string> = { coral: styles.bandCoral, sky: styles.bandSky, leaf: styles.bandLeaf };
export default function CardGridPaper({
cards = [
{ title: "겹치기", desc: "깊이는 층으로", band: "coral", icon: "stack" },
{ title: "칠하기", desc: "색은 세 가지만", band: "sky", icon: "brush" },
{ title: "붙이기", desc: "그림자로 고정", band: "leaf", icon: "sparkle" },
],
duration = 2000,
easing = "cubic-bezier(.2,.8,.2,1)",
stagger = 220,
}: CardGridPaperProps) {
return (
<section className={styles.cardpaper}>
{cards.map((c, i) => {
const vars: Vars = {
"--duration": `${duration}ms`, "--easing": easing, "--delay": `${-stagger * i}ms`,
};
return (
<article key={c.title} className={`${styles.card} ${BAND[c.band]}`} style={vars}>
<span className={styles.ic} aria-hidden="true">{ICON[c.icon]}</span>
<h2 className={styles.t}>{c.title}</h2>
<p className={styles.d}>{c.desc}</p>
</article>
);
})}
</section>
);
}03 색종이 머리띠 카드 격자 — 측정 누적면적 17.899% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 종이 질감 디자인 랜딩 키트, 오려 붙인 섹션 9개
이 데모가 속한 글
종이 질감 디자인 랜딩 키트, 오려 붙인 섹션 9개종이 질감 디자인은 색종이를 가위로 오려 붙인 것처럼 면마다 흐림 없는 그림자로 두께를 주고, 색은 다섯 가지 안에서만 쓰는 스타일입니다. 종이 사진을 깔지 않고 그림자 값 하나만으로 종이처럼 보이게 만드는 것이 전 이 글의 데모 전부 보기


