06손글씨 밑줄 후기
후기 문장의 한 구절 아래로 삐뚤빼뚤한 SVG 선이 왼쪽부터 그어지고, 다 그어지면 지웠다가 다시 긋습니다.
쓰임후기 카드, 본문 안 강조 구절
stroke-dashoffsetSVG pathradius 4

<main class="stage">
<figure class="tcol">
<span class="tcol__tape" aria-hidden="true"></span>
<span class="tcol__quote" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256" fill="currentColor"><path d="M108,72v72H40a8,8,0,0,1-8-8V72a8,8,0,0,1,8-8h60A8,8,0,0,1,108,72Zm108-8H156a8,8,0,0,0-8,8v64a8,8,0,0,0,8,8h68V72A8,8,0,0,0,216,64Z" opacity="0.2"/><path d="M100,56H40A16,16,0,0,0,24,72v64a16,16,0,0,0,16,16h60v8a32,32,0,0,1-32,32,8,8,0,0,0,0,16,48.05,48.05,0,0,0,48-48V72A16,16,0,0,0,100,56Zm0,80H40V72h60ZM216,56H156a16,16,0,0,0-16,16v64a16,16,0,0,0,16,16h60v8a32,32,0,0,1-32,32,8,8,0,0,0,0,16,48.05,48.05,0,0,0,48-48V72A16,16,0,0,0,216,56Zm0,80H156V72h60Z"/></svg>
</span>
<blockquote class="tcol__text">
잘라 붙인 화면인데<br>
<span class="tcol__mark">읽는 순서는 안 흔들려요</span>
<svg class="tcol__line" viewBox="0 0 200 12" aria-hidden="true" preserveAspectRatio="none">
<path d="M3 8 C 28 2, 52 11, 78 6 S 132 2, 158 8 S 186 4, 197 6" />
</svg>
</blockquote>
<figcaption class="tcol__by">
<span class="tcol__dot" aria-hidden="true">ㅈ</span>
<span class="tcol__who">정 · 잡지 에디터</span>
</figcaption>
</figure>
</main>@use "../../../../site/static/demo-tokens" as *;
// 콜라주·맥시멀 팔레트 (01 과 같은 값)
$cg-cream: #fbf3e4;
$cg-sheet: #ffffff;
$cg-ink: #241d2e;
$cg-slate: #57506a;
$cg-coral: #bb7f74;
$cg-lemon: #d1c8a3;
$cg-lime: #bfce9c;
$serif: Georgia, "Nanum Myeongjo", "Times New Roman", serif;
$duration: $dur-loop; // 선이 다 그어지고 지워지는 한 주기
$easing: $ease-out; // 손으로 긋는 선은 끝에서 느려진다
$color: $cg-coral; // 밑줄 색
$line-len: 230; // path 실측 길이보다 넉넉히 — dasharray·dashoffset 에 같이 쓴다
@include stage($cg-cream);
.tcol {
position: relative;
box-sizing: border-box;
width: clamp(216px, 74vw, 276px);
margin: 0;
padding: $sp-5 $sp-5 $sp-4;
border-radius: $r-xs;
background: $cg-sheet;
box-shadow: 0 6px 0 rgba($cg-ink, .16);
transform: rotate(-1.5deg);
}
// 비뚤게 붙인 마스킹 테이프 한 장
.tcol__tape {
position: absolute;
top: -10px;
left: 50%;
width: 72px;
height: 20px;
margin-left: -36px;
border-radius: 0;
background: rgba($cg-lime, .85);
transform: rotate(-5deg);
}
.tcol__quote {
display: block;
color: $cg-coral;
font-size: 20px;
line-height: 1;
}
.tcol__text {
position: relative;
margin: $sp-2 0 0;
color: $cg-ink;
font-family: $serif;
font-weight: 700;
font-size: clamp(14px, 3.4vw, 17px);
line-height: 1.5;
}
.tcol__mark { position: relative; z-index: 1; }
// 손으로 그은 것 같은 밑줄 — 글자 줄 아래에 딱 붙는다
.tcol__line {
position: absolute;
left: 0;
bottom: -4px;
width: 100%;
height: 12px;
overflow: visible;
fill: none;
stroke: $cg-coral;
stroke-width: 4;
stroke-linecap: round;
stroke-dasharray: $line-len;
animation-name: inkDraw;
animation-duration: $duration;
animation-timing-function: $easing;
animation-iteration-count: infinite;
}
.tcol__by {
display: flex;
align-items: center;
gap: $sp-2;
margin-top: $sp-4;
}
.tcol__dot {
width: 24px;
aspect-ratio: 1;
display: grid;
place-items: center;
border-radius: 50%;
background: $cg-lemon;
color: $cg-ink;
font-weight: 700;
font-size: 12px;
line-height: 1;
transform: rotate(6deg);
}
.tcol__who {
color: $cg-slate;
font-weight: 600;
font-size: 12px;
line-height: 1;
}
// 데모: 왼쪽부터 그어졌다가(오프셋 +→0) 왼쪽부터 지워진다(0→-) — 되돌아가는 구간이 없다
@keyframes inkDraw {
0% { stroke-dashoffset: #{$line-len}; }
45% { stroke-dashoffset: 0; }
70% { stroke-dashoffset: 0; }
100% { stroke-dashoffset: -#{$line-len}; }
}
@media (max-width: 360px), (max-height: 230px) {
.tcol { width: 208px; padding: $sp-4 $sp-3 $sp-3; }
.tcol__quote { font-size: 15px; }
.tcol__text { font-size: 13px; }
.tcol__by { margin-top: $sp-2; }
}
@media (prefers-reduced-motion: reduce) {
.tcol__line { animation: none !important; stroke-dashoffset: 0; }
}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);
}
.tcol {
position: relative;
box-sizing: border-box;
width: clamp(216px, 74vw, 276px);
margin: 0;
padding: 20px 20px 16px;
border-radius: 4px;
background: #ffffff;
box-shadow: 0 6px 0 rgba(36, 29, 46, 0.16);
transform: rotate(-1.5deg);
}
.tcol__tape {
position: absolute;
top: -10px;
left: 50%;
width: 72px;
height: 20px;
margin-left: -36px;
border-radius: 0;
background: rgba(191, 206, 156, 0.85);
transform: rotate(-5deg);
}
.tcol__quote {
display: block;
color: #bb7f74;
font-size: 20px;
line-height: 1;
}
.tcol__text {
position: relative;
margin: 8px 0 0;
color: #241d2e;
font-family: Georgia, "Nanum Myeongjo", "Times New Roman", serif;
font-weight: 700;
font-size: clamp(14px, 3.4vw, 17px);
line-height: 1.5;
}
.tcol__mark {
position: relative;
z-index: 1;
}
.tcol__line {
position: absolute;
left: 0;
bottom: -4px;
width: 100%;
height: 12px;
overflow: visible;
fill: none;
stroke: #bb7f74;
stroke-width: 4;
stroke-linecap: round;
stroke-dasharray: 230;
animation-name: inkDraw;
animation-duration: 2s;
animation-timing-function: ease-out;
animation-iteration-count: infinite;
}
.tcol__by {
display: flex;
align-items: center;
gap: 8px;
margin-top: 16px;
}
.tcol__dot {
width: 24px;
aspect-ratio: 1;
display: grid;
place-items: center;
border-radius: 50%;
background: #d1c8a3;
color: #241d2e;
font-weight: 700;
font-size: 12px;
line-height: 1;
transform: rotate(6deg);
}
.tcol__who {
color: #57506a;
font-weight: 600;
font-size: 12px;
line-height: 1;
}
@keyframes inkDraw {
0% {
stroke-dashoffset: 230;
}
45% {
stroke-dashoffset: 0;
}
70% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -230;
}
}
@media (max-width: 360px), (max-height: 230px) {
.tcol {
width: 208px;
padding: 16px 12px 12px;
}
.tcol__quote {
font-size: 15px;
}
.tcol__text {
font-size: 13px;
}
.tcol__by {
margin-top: 8px;
}
}
@media (prefers-reduced-motion: reduce) {
.tcol__line {
animation: none !important;
stroke-dashoffset: 0;
}
}import type { CSSProperties, ReactNode } from "react";
import styles from "./TestimonialCollage.module.scss";
export type TestimonialCollageProps = {
lead?: string;
/** 밑줄이 그어지는 구절 */
marked?: string;
initial?: string;
who?: string;
quoteIcon?: ReactNode;
duration?: number;
easing?: string;
color?: string;
};
type Vars = CSSProperties & { "--duration"?: string; "--easing"?: string; "--color"?: string };
export default function TestimonialCollage({
lead = "잘라 붙인 화면인데",
marked = "읽는 순서는 안 흔들려요",
initial = "ㅈ",
who = "정 · 잡지 에디터",
quoteIcon,
duration = 2000,
easing = "ease-out",
color = "#d93a1e",
}: TestimonialCollageProps) {
const vars: Vars = { "--duration": `${duration}ms`, "--easing": easing, "--color": color };
return (
<figure className={styles.tcol} style={vars}>
<span className={styles.tape} aria-hidden="true" />
<span className={styles.quote} aria-hidden="true">{quoteIcon}</span>
<blockquote className={styles.text}>
{lead}<br />
<span className={styles.mark}>{marked}</span>
<svg className={styles.line} viewBox="0 0 200 12" aria-hidden="true" preserveAspectRatio="none">
<path d="M3 8 C 28 2, 52 11, 78 6 S 132 2, 158 8 S 186 4, 197 6" />
</svg>
</blockquote>
<figcaption className={styles.by}>
<span className={styles.dot} aria-hidden="true">{initial}</span>
<span className={styles.who}>{who}</span>
</figcaption>
</figure>
);
}06 손글씨 밑줄 후기 — 측정 누적면적 0.803% · 움직인 프레임 14/23GODRICH 원작 · zip 에 SCSS·React 포함 · 맥시멀리즘 디자인 랜딩 키트, 겹쳐 붙인 콜라주 9종
이 데모가 속한 글
맥시멀리즘 디자인 랜딩 키트, 겹쳐 붙인 콜라주 9종맥시멀리즘 디자인은 여백을 비우는 대신 색면·큰 활자·스티커를 겹쳐 붙여 화면을 꽉 채우는 스타일입니다. 잡지에서 오려 붙인 콜라주가 그 대표 얼굴이고, 이 키트는 사진 파일 없이 CSS 값만으로 그 인상을 냅니다. 이 글의 데모 전부 보기


