05별표 동그라미 요금제
세 요금제 카드는 저마다 다른 크레용 색이고, 추천 플랜의 가격 숫자만 손으로 그린 동그라미가 스스로 둘러 그려지며 옆에 손그림 별 두 개가 반짝입니다. 표 없이도 어디를 봐야 하는지 바로 보입니다.
쓰임3단 요금제, 학원·클래스 수강료
stroke-dashoffset 원반짝이는 별radius 24

<main class="stage">
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
<filter id="rough5" x="-40%" y="-40%" width="180%" height="180%">
<feTurbulence type="fractalNoise" baseFrequency="0.05 0.08" numOctaves="2" seed="21" result="n"/>
<feDisplacementMap in="SourceGraphic" in2="n" scale="5" xChannelSelector="R" yChannelSelector="G"/>
</filter>
</svg>
<div class="pricecrayon">
<div class="pricecrayon__card">
<p class="pricecrayon__name">새싹</p>
<p class="pricecrayon__price">무료</p>
<p class="pricecrayon__note">영원히</p>
</div>
<div class="pricecrayon__card pricecrayon__card--main">
<span class="pricecrayon__star pricecrayon__star--a" aria-hidden="true">✦</span>
<span class="pricecrayon__star pricecrayon__star--b" aria-hidden="true">✦</span>
<p class="pricecrayon__name">크레용</p>
<span class="pricecrayon__price-wrap">
<svg class="pricecrayon__ring" viewBox="0 0 100 46" aria-hidden="true">
<path class="pricecrayon__ring-path" d="M50 4 C 22 3, 5 14, 6 23 C 7 34, 26 42, 50 42 C 74 42, 93 34, 94 23 C 95 13, 78 3, 50 5" />
</svg>
<p class="pricecrayon__price">월 12,000원</p>
</span>
<p class="pricecrayon__note">가장 인기</p>
</div>
<div class="pricecrayon__card">
<p class="pricecrayon__name">패밀리</p>
<p class="pricecrayon__price">월 9,000원</p>
<p class="pricecrayon__note">3인 이상</p>
</div>
</div>
</main>@use "../../../../site/static/demo-tokens" as *;
$duration: $dur-loop; // 동그라미가 한 번 그려지는 주기
$easing: $ease-out; // 선이 그려지는 곡선
$color: $stage-ink; // 글자 색 기본값(토큰) — 아래 크레용 잉크로 덮는다
$crayon-paper: #fff8ef;
$crayon-ink: #33261c;
$crayon-red: #dbb6b7;
$crayon-yellow: #d1c5a2;
$crayon-blue: #9cb8ce;
$crayon-green: #6dbe6d;
$crayon-purple: #cbbfe0;
$crayon-yellow-tint: #fff3cc;
$crayon-blue-tint: #dff0fc;
$crayon-green-tint: #e2f5e2;
@include stage($crayon-paper);
.pricecrayon {
display: flex;
align-items: center;
gap: $sp-3;
width: clamp(240px, 86vw, 360px);
}
.pricecrayon__card {
position: relative;
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: $sp-1;
border-radius: $r-card;
padding: $sp-4 $sp-2;
text-align: center;
background: $crayon-blue-tint;
}
.pricecrayon__card:first-child { background: $crayon-green-tint; }
.pricecrayon__card:last-child { background: $crayon-blue-tint; }
.pricecrayon__card--main {
background: $crayon-yellow-tint;
border: 3px solid $crayon-ink;
transform: scale(1.1);
z-index: 1;
}
.pricecrayon__name {
margin: 0;
color: $crayon-ink;
font-weight: 700;
font-size: clamp(10px, 2.6vw, 12px);
}
.pricecrayon__price-wrap {
position: relative;
display: inline-flex;
}
.pricecrayon__price {
margin: 0;
position: relative;
z-index: 1;
color: $crayon-ink;
font-weight: 700;
font-size: clamp(12px, 3vw, 14px);
padding: $sp-1 $sp-1;
}
.pricecrayon__note {
margin: 0;
color: rgba($crayon-ink, .72);
font-weight: 500;
font-size: 10px;
}
.pricecrayon__ring {
position: absolute;
inset: -6px -10px;
width: calc(100% + 20px);
height: calc(100% + 12px);
pointer-events: none;
filter: url(#rough5);
}
.pricecrayon__ring-path {
fill: none;
stroke: $crayon-red;
stroke-width: 3.2;
stroke-linecap: round;
stroke-dasharray: 190;
animation: ringDraw $duration $easing infinite;
}
.pricecrayon__star {
position: absolute;
color: $crayon-yellow;
font-size: 14px;
line-height: 1;
animation: starTwinkle $duration $easing infinite;
}
.pricecrayon__star--a { top: -6px; left: 2px; animation-delay: 0ms; }
.pricecrayon__star--b { top: 4px; right: -4px; animation-delay: 520ms; }
// 데모: 추천 플랜 가격을 손그림 동그라미가 둘러 그렸다 지우기를 반복하고, 옆의 별이 번갈아 반짝인다
@keyframes ringDraw {
0% { stroke-dashoffset: 190; }
50% { stroke-dashoffset: 0; }
100% { stroke-dashoffset: -190; }
}
@keyframes starTwinkle {
0%, 100% { opacity: .25; transform: scale(.8); }
50% { opacity: 1; transform: scale(1.15); }
}
@media (max-width: 340px), (max-height: 220px) {
.pricecrayon { gap: $sp-1; }
.pricecrayon__card { padding: $sp-2 $sp-1; }
.pricecrayon__card--main { transform: scale(1.05); }
.pricecrayon__note { display: none; }
}
@media (prefers-reduced-motion: reduce) {
.pricecrayon__ring-path, .pricecrayon__star {
animation: none !important;
}
.pricecrayon__ring-path { stroke-dashoffset: 0; }
.pricecrayon__star { opacity: 1; transform: none; }
}html, body {
margin: 0;
overflow: hidden;
}
.stage {
box-sizing: border-box;
min-height: 100vh;
display: grid;
place-items: center;
margin: 0;
background: #fff8ef;
font-family: -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
padding: clamp(8px, 4vw, 24px);
}
.pricecrayon {
display: flex;
align-items: center;
gap: 12px;
width: clamp(240px, 86vw, 360px);
}
.pricecrayon__card {
position: relative;
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
border-radius: 16px;
padding: 16px 8px;
text-align: center;
background: #dff0fc;
}
.pricecrayon__card:first-child {
background: #e2f5e2;
}
.pricecrayon__card:last-child {
background: #dff0fc;
}
.pricecrayon__card--main {
background: #fff3cc;
border: 3px solid #33261c;
transform: scale(1.1);
z-index: 1;
}
.pricecrayon__name {
margin: 0;
color: #33261c;
font-weight: 700;
font-size: clamp(10px, 2.6vw, 12px);
}
.pricecrayon__price-wrap {
position: relative;
display: inline-flex;
}
.pricecrayon__price {
margin: 0;
position: relative;
z-index: 1;
color: #33261c;
font-weight: 700;
font-size: clamp(12px, 3vw, 14px);
padding: 4px 4px;
}
.pricecrayon__note {
margin: 0;
color: rgba(51, 38, 28, 0.72);
font-weight: 500;
font-size: 10px;
}
.pricecrayon__ring {
position: absolute;
inset: -6px -10px;
width: calc(100% + 20px);
height: calc(100% + 12px);
pointer-events: none;
filter: url(#rough5);
}
.pricecrayon__ring-path {
fill: none;
stroke: #dbb6b7;
stroke-width: 3.2;
stroke-linecap: round;
stroke-dasharray: 190;
animation: ringDraw 2s ease-out infinite;
}
.pricecrayon__star {
position: absolute;
color: #d1c5a2;
font-size: 14px;
line-height: 1;
animation: starTwinkle 2s ease-out infinite;
}
.pricecrayon__star--a {
top: -6px;
left: 2px;
animation-delay: 0ms;
}
.pricecrayon__star--b {
top: 4px;
right: -4px;
animation-delay: 520ms;
}
@keyframes ringDraw {
0% {
stroke-dashoffset: 190;
}
50% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -190;
}
}
@keyframes starTwinkle {
0%, 100% {
opacity: 0.25;
transform: scale(0.8);
}
50% {
opacity: 1;
transform: scale(1.15);
}
}
@media (max-width: 340px), (max-height: 220px) {
.pricecrayon {
gap: 4px;
}
.pricecrayon__card {
padding: 8px 4px;
}
.pricecrayon__card--main {
transform: scale(1.05);
}
.pricecrayon__note {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.pricecrayon__ring-path, .pricecrayon__star {
animation: none !important;
}
.pricecrayon__ring-path {
stroke-dashoffset: 0;
}
.pricecrayon__star {
opacity: 1;
transform: none;
}
}import type { CSSProperties } from "react";
import styles from "./PricingCrayon.module.scss";
export type PricingCrayonProps = {
duration?: number;
easing?: string;
color?: string;
};
type Vars = CSSProperties & { "--duration"?: string; "--easing"?: string; "--color"?: string };
export default function PricingCrayon({
duration = 2000,
easing = "ease-out",
color = "#ff5a5f",
}: PricingCrayonProps) {
const vars: Vars = { "--duration": `${duration}ms`, "--easing": easing, "--color": color };
return (
<div className={styles.wrap} style={vars}>
<svg width="0" height="0" style={{ position: "absolute" }} aria-hidden="true" focusable="false">
<filter id="pc-rough" x="-40%" y="-40%" width="180%" height="180%">
<feTurbulence type="fractalNoise" baseFrequency={0.06} numOctaves={2} seed={21} result="n" />
<feDisplacementMap in="SourceGraphic" in2="n" scale={5} xChannelSelector="R" yChannelSelector="G" />
</filter>
</svg>
<div className={`${styles.card} ${styles.green}`}>
<p className={styles.name}>새싹</p>
<p className={styles.price}>무료</p>
<p className={styles.note}>영원히</p>
</div>
<div className={`${styles.card} ${styles.main}`}>
<span className={`${styles.star} ${styles.starA}`} aria-hidden="true">✦</span>
<span className={`${styles.star} ${styles.starB}`} aria-hidden="true">✦</span>
<p className={styles.name}>크레용</p>
<span className={styles.priceWrap}>
<svg className={styles.ring} viewBox="0 0 100 46" aria-hidden="true">
<path className={styles.ringPath} d="M50 4 C 22 3, 5 14, 6 23 C 7 34, 26 42, 50 42 C 74 42, 93 34, 94 23 C 95 13, 78 3, 50 5" />
</svg>
<p className={styles.price}>월 12,000원</p>
</span>
<p className={styles.note}>가장 인기</p>
</div>
<div className={`${styles.card} ${styles.blue}`}>
<p className={styles.name}>패밀리</p>
<p className={styles.price}>월 9,000원</p>
<p className={styles.note}>3인 이상</p>
</div>
</div>
);
}05 별표 동그라미 요금제 — 측정 누적면적 0.613% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 손그림 디자인 랜딩 UI 키트, 크레용 섹션 9개
이 데모가 속한 글
손그림 디자인 랜딩 UI 키트, 크레용 섹션 9개손그림 디자인은 굵고 삐뚤빼뚤한 크레용 선으로 테두리를 그리고, 그 선만 SVG 필터로 살짝 흔들어 종이 위에 손으로 그은 낙서처럼 보이게 만드는 스타일입니다. 동네 미술학원이나 어린이 브랜드 사이트에서 본 그 느낌 이 글의 데모 전부 보기


