07Overlapping pricing layers
Two price cards overlap corner to corner, and the recommended one widens its shadow as it lifts.
Best forPlan comparison and recommended-tier emphasis
음수 margin 겹침그림자 확장radius 4

<main class="stage">
<section class="pcol">
<article class="pcol__plan pcol__plan--base">
<p class="pcol__tier">BASIC</p>
<p class="pcol__price">₩0</p>
<p class="pcol__note">3 parts</p>
</article>
<article class="pcol__plan pcol__plan--pick">
<span class="pcol__stamp" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256" fill="currentColor"><path d="M232,128c0,12.51-17.82,21.95-22.68,33.69-4.68,11.32,1.42,30.65-7.78,39.85s-28.53,3.1-39.85,7.78C150,214.18,140.5,232,128,232s-22-17.82-33.69-22.68c-11.32-4.68-30.65,1.42-39.85-7.78s-3.1-28.53-7.78-39.85C41.82,150,24,140.5,24,128s17.82-22,22.68-33.69C51.36,83,45.26,63.66,54.46,54.46S83,51.36,94.31,46.68C106.05,41.82,115.5,24,128,24S150,41.82,161.69,46.68c11.32,4.68,30.65-1.42,39.85,7.78s3.1,28.53,7.78,39.85C214.18,106.05,232,115.5,232,128Z" opacity="0.2"/><path d="M225.86,102.82c-3.77-3.94-7.67-8-9.14-11.57-1.36-3.27-1.44-8.69-1.52-13.94-.15-9.76-.31-20.82-8-28.51s-18.75-7.85-28.51-8c-5.25-.08-10.67-.16-13.94-1.52-3.56-1.47-7.63-5.37-11.57-9.14C146.28,23.51,138.44,16,128,16s-18.27,7.51-25.18,14.14c-3.94,3.77-8,7.67-11.57,9.14C88,40.64,82.56,40.72,77.31,40.8c-9.76.15-20.82.31-28.51,8S41,67.55,40.8,77.31c-.08,5.25-.16,10.67-1.52,13.94-1.47,3.56-5.37,7.63-9.14,11.57C23.51,109.72,16,117.56,16,128s7.51,18.27,14.14,25.18c3.77,3.94,7.67,8,9.14,11.57,1.36,3.27,1.44,8.69,1.52,13.94.15,9.76.31,20.82,8,28.51s18.75,7.85,28.51,8c5.25.08,10.67.16,13.94,1.52,3.56,1.47,7.63,5.37,11.57,9.14C109.72,232.49,117.56,240,128,240s18.27-7.51,25.18-14.14c3.94-3.77,8-7.67,11.57-9.14,3.27-1.36,8.69-1.44,13.94-1.52,9.76-.15,20.82-.31,28.51-8s7.85-18.75,8-28.51c.08-5.25.16-10.67,1.52-13.94,1.47-3.56,5.37-7.63,9.14-11.57C232.49,146.28,240,138.44,240,128S232.49,109.73,225.86,102.82Zm-11.55,39.29c-4.79,5-9.75,10.17-12.38,16.52-2.52,6.1-2.63,13.07-2.73,19.82-.1,7-.21,14.33-3.32,17.43s-10.39,3.22-17.43,3.32c-6.75.1-13.72.21-19.82,2.73-6.35,2.63-11.52,7.59-16.52,12.38S132,224,128,224s-9.15-4.92-14.11-9.69-10.17-9.75-16.52-12.38c-6.1-2.52-13.07-2.63-19.82-2.73-7-.1-14.33-.21-17.43-3.32s-3.22-10.39-3.32-17.43c-.1-6.75-.21-13.72-2.73-19.82-2.63-6.35-7.59-11.52-12.38-16.52S32,132,32,128s4.92-9.15,9.69-14.11,9.75-10.17,12.38-16.52c2.52-6.1,2.63-13.07,2.73-19.82.1-7,.21-14.33,3.32-17.43S70.51,56.9,77.55,56.8c6.75-.1,13.72-.21,19.82-2.73,6.35-2.63,11.52-7.59,16.52-12.38S124,32,128,32s9.15,4.92,14.11,9.69,10.17,9.75,16.52,12.38c6.1,2.52,13.07,2.63,19.82,2.73,7,.1,14.33.21,17.43,3.32s3.22,10.39,3.32,17.43c.1,6.75.21,13.72,2.73,19.82,2.63,6.35,7.59,11.52,12.38,16.52S224,124,224,128,219.08,137.15,214.31,142.11ZM173.66,98.34a8,8,0,0,1,0,11.32l-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35A8,8,0,0,1,173.66,98.34Z"/></svg>
</span>
<p class="pcol__tier">STUDIO</p>
<p class="pcol__price">₩9</p>
<p class="pcol__note">9 parts + zip</p>
</article>
</section>
</main>@use "../../../../site/static/demo-tokens" as *;
// 콜라주·맥시멀 팔레트 (01 과 같은 값). 코랄 면 위 글자만 흰색(4.59:1)
$cg-cream: #fbf3e4;
$cg-sheet: #ffffff;
$cg-ink: #241d2e;
$cg-slate: #57506a;
$cg-coral: #bb7f74;
$cg-lemon: #d1c8a3;
$serif: Georgia, "Nanum Myeongjo", "Times New Roman", serif;
$duration: $dur-loop; // 추천 카드가 떴다 내려앉는 한 주기
$easing: $ease-spring;
$color: $cg-coral; // 추천 카드의 면 색
@include stage($cg-cream);
.pcol {
display: flex;
align-items: flex-end;
isolation: isolate;
}
.pcol__plan {
position: relative;
box-sizing: border-box;
width: 116px;
padding: $sp-4 $sp-3;
border-radius: $r-xs;
box-shadow: 0 5px 0 rgba($cg-ink, .16);
}
// 뒤 카드 — 앞 카드에 모서리를 덮인다
.pcol__plan--base {
z-index: 1;
background: $cg-sheet;
color: $cg-ink;
transform: rotate(-3deg);
}
// 앞 카드 — 음수 margin 으로 겹치고 z-index 로 위에 올라간다
.pcol__plan--pick {
z-index: 2;
margin-left: -$sp-5;
margin-bottom: $sp-4;
background: $cg-coral;
color: $cg-sheet;
animation-name: planLift;
animation-duration: $duration;
animation-timing-function: $easing;
animation-iteration-count: infinite;
}
.pcol__stamp {
position: absolute;
z-index: 3;
top: -14px;
right: -12px;
width: 34px;
aspect-ratio: 1;
display: grid;
place-items: center;
border-radius: 50%;
background: $cg-lemon;
color: $cg-ink;
font-size: 20px;
transform: rotate(16deg);
box-shadow: 0 3px 0 rgba($cg-ink, .2);
}
.pcol__tier {
margin: 0;
font-weight: 700;
font-size: 11px;
line-height: 1;
letter-spacing: .16em;
}
.pcol__plan--base .pcol__tier { color: $cg-coral; }
.pcol__price {
margin: $sp-2 0 0;
font-family: $serif;
font-weight: 700;
font-size: 30px;
line-height: 1;
}
.pcol__note {
margin: $sp-2 0 0;
font-weight: 500;
font-size: 11px;
line-height: 1.3;
}
.pcol__plan--base .pcol__note { color: $cg-slate; }
// 데모: 앞 카드가 뜨는 동안 그림자 두께가 같이 늘어난다 — 겹친 층이 층으로 읽힌다
@keyframes planLift {
0%, 100% { transform: rotate(2deg) translateY(0); box-shadow: 0 5px 0 rgba($cg-ink, .16); }
50% { transform: rotate(2deg) translateY(-12px); box-shadow: 0 17px 0 rgba($cg-ink, .12); }
}
@media (max-width: 360px), (max-height: 230px) {
.pcol__plan { width: 92px; padding: $sp-3 $sp-2; }
.pcol__price { font-size: 22px; }
.pcol__note { font-size: 10px; }
.pcol__stamp { width: 26px; font-size: 15px; top: -10px; right: -8px; }
}
@media (prefers-reduced-motion: reduce) {
.pcol__plan--pick { animation: none !important; transform: rotate(2deg); }
}html, body {
margin: 0;
overflow: hidden;
}
.stage {
box-sizing: border-box;
min-height: 100vh;
display: grid;
place-items: center;
margin: 0;
background: #fbf3e4;
font-family: -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
padding: clamp(8px, 4vw, 24px);
}
.pcol {
display: flex;
align-items: flex-end;
isolation: isolate;
}
.pcol__plan {
position: relative;
box-sizing: border-box;
width: 116px;
padding: 16px 12px;
border-radius: 4px;
box-shadow: 0 5px 0 rgba(36, 29, 46, 0.16);
}
.pcol__plan--base {
z-index: 1;
background: #ffffff;
color: #241d2e;
transform: rotate(-3deg);
}
.pcol__plan--pick {
z-index: 2;
margin-left: -20px;
margin-bottom: 16px;
background: #bb7f74;
color: #ffffff;
animation-name: planLift;
animation-duration: 2s;
animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1);
animation-iteration-count: infinite;
}
.pcol__stamp {
position: absolute;
z-index: 3;
top: -14px;
right: -12px;
width: 34px;
aspect-ratio: 1;
display: grid;
place-items: center;
border-radius: 50%;
background: #d1c8a3;
color: #241d2e;
font-size: 20px;
transform: rotate(16deg);
box-shadow: 0 3px 0 rgba(36, 29, 46, 0.2);
}
.pcol__tier {
margin: 0;
font-weight: 700;
font-size: 11px;
line-height: 1;
letter-spacing: 0.16em;
}
.pcol__plan--base .pcol__tier {
color: #bb7f74;
}
.pcol__price {
margin: 8px 0 0;
font-family: Georgia, "Nanum Myeongjo", "Times New Roman", serif;
font-weight: 700;
font-size: 30px;
line-height: 1;
}
.pcol__note {
margin: 8px 0 0;
font-weight: 500;
font-size: 11px;
line-height: 1.3;
}
.pcol__plan--base .pcol__note {
color: #57506a;
}
@keyframes planLift {
0%, 100% {
transform: rotate(2deg) translateY(0);
box-shadow: 0 5px 0 rgba(36, 29, 46, 0.16);
}
50% {
transform: rotate(2deg) translateY(-12px);
box-shadow: 0 17px 0 rgba(36, 29, 46, 0.12);
}
}
@media (max-width: 360px), (max-height: 230px) {
.pcol__plan {
width: 92px;
padding: 12px 8px;
}
.pcol__price {
font-size: 22px;
}
.pcol__note {
font-size: 10px;
}
.pcol__stamp {
width: 26px;
font-size: 15px;
top: -10px;
right: -8px;
}
}
@media (prefers-reduced-motion: reduce) {
.pcol__plan--pick {
animation: none !important;
transform: rotate(2deg);
}
}import type { CSSProperties, ReactNode } from "react";
import styles from "./PricingCollage.module.scss";
export type PricingCollagePlan = { tier: string; price: string; note: string };
export type PricingCollageProps = {
base?: PricingCollagePlan;
pick?: PricingCollagePlan;
stampIcon?: ReactNode;
duration?: number;
easing?: string;
color?: string;
};
type Vars = CSSProperties & { "--duration"?: string; "--easing"?: string; "--color"?: string };
export default function PricingCollage({
base = { tier: "BASIC", price: "₩0", note: "부품 3개" },
pick = { tier: "STUDIO", price: "₩9", note: "부품 9개 + zip" },
stampIcon,
duration = 2000,
easing = "cubic-bezier(.2, .8, .2, 1)",
color = "#d93a1e",
}: PricingCollageProps) {
const vars: Vars = { "--duration": `${duration}ms`, "--easing": easing, "--color": color };
return (
<section className={styles.pcol} style={vars}>
<article className={`${styles.plan} ${styles.planBase}`}>
<p className={styles.tier}>{base.tier}</p>
<p className={styles.price}>{base.price}</p>
<p className={styles.note}>{base.note}</p>
</article>
<article className={`${styles.plan} ${styles.planPick}`}>
<span className={styles.stamp} aria-hidden="true">{stampIcon}</span>
<p className={styles.tier}>{pick.tier}</p>
<p className={styles.price}>{pick.price}</p>
<p className={styles.note}>{pick.note}</p>
</article>
</section>
);
}07 Overlapping pricing layers — Measured area 5.199% · moving frames 18/23Original by GODRICH · SCSS and React ship in the zip · Maximalist Web Design: 9 Collage Landing Sections
The post this demo lives in
Maximalist Web Design: 9 Collage Landing SectionsMaximalist web design fills the screen instead of emptying it, stacking color fields, oversized type, and stickers until See all demos in this post


