08Quét hai tông màu
Cùng một câu chữ được xếp chồng hai lớp màu khác nhau, còn clip-path của lớp trên quét từ trái sang phải để màu lớp dưới lộ dần ra. Ranh giới giữa hai lớp luôn rõ và cứng chứ không mờ dần như gradient.
Dùng choLàm nổi bảng giá, nhấn câu copy chiến dịch
clip-path 스윕두 겹 텍스트단색 경계

<main class="stage">
<div class="sweep">
<span class="sweep__base" data-split>Giảm nửa giá</span>
<span class="sweep__top" aria-hidden="true" data-split>Giảm nửa giá</span>
</div>
</main>@use "../../../../site/static/demo-tokens" as *;
$duration: $dur-loop;
$easing: $ease-spring;
$base: $subject-ink; // 아래 색
$sweep: $subject-blue; // 위에서 걷히는 색
@include stage($stage-paper);
.sweep {
position: relative;
font-weight: 800; font-size: clamp(26px, 8.4vw, 42px); line-height: 1.2; font-family: inherit;
}
.sweep__base, .sweep__top {
display: block;
margin: 0;
text-align: center;
}
.sweep__base { color: $base; }
.sweep__top {
position: absolute;
inset: 0;
color: $sweep;
animation: sweep-wipe $duration $easing infinite;
}
.sweep .letter {
display: inline-block;
animation: letter-blur-in $duration $easing infinite;
animation-delay: calc(var(--i) * 30ms + var(--n) * 50ms);
}
@keyframes sweep-wipe {
0%, 4% { clip-path: inset(0 100% 0 0); }
40%, 62% { clip-path: inset(0 0 0 0); }
96%, 100% { clip-path: inset(0 100% 0 0); }
}
@keyframes letter-blur-in {
0%, 2% { filter: blur(9px); }
14%, 100% { filter: blur(0); }
}
@media (prefers-reduced-motion: reduce) {
.sweep__top { animation: none; clip-path: inset(0 0 0 0); }
.sweep .letter { animation: none; filter: none; }
}html, body {
margin: 0;
overflow: hidden;
}
.stage {
box-sizing: border-box;
min-height: 100vh;
display: grid;
place-items: center;
margin: 0;
background: #ffffff;
font-family: -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
padding: clamp(8px, 4vw, 24px);
}
.sweep {
position: relative;
font-weight: 800;
font-size: clamp(26px, 8.4vw, 42px);
line-height: 1.2;
font-family: inherit;
}
.sweep__base, .sweep__top {
display: block;
margin: 0;
text-align: center;
}
.sweep__base {
color: #17141a;
}
.sweep__top {
position: absolute;
inset: 0;
color: #2f6df6;
animation: sweep-wipe 2s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}
.sweep .letter {
display: inline-block;
animation: letter-blur-in 2s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
animation-delay: calc(var(--i) * 30ms + var(--n) * 50ms);
}
@keyframes sweep-wipe {
0%, 4% {
clip-path: inset(0 100% 0 0);
}
40%, 62% {
clip-path: inset(0 0 0 0);
}
96%, 100% {
clip-path: inset(0 100% 0 0);
}
}
@keyframes letter-blur-in {
0%, 2% {
filter: blur(9px);
}
14%, 100% {
filter: blur(0);
}
}
@media (prefers-reduced-motion: reduce) {
.sweep__top {
animation: none;
clip-path: inset(0 0 0 0);
}
.sweep .letter {
animation: none;
filter: none;
}
}(function(){
function splitLetters(el){
var text = el.textContent;
el.textContent = "";
Array.from(text).forEach(function(ch, i){
var span = document.createElement("span");
span.className = "letter";
var seed = Math.sin((i + 1) * 12.9898) * 43758.5453;
var noise = seed - Math.floor(seed);
span.style.setProperty("--i", i);
span.style.setProperty("--n", noise.toFixed(3));
span.textContent = ch === " " ? " " : ch;
el.appendChild(span);
});
}
document.querySelectorAll("[data-split]").forEach(splitLetters);
})();import type { CSSProperties } from "react";
import styles from "./TwoToneSweep.module.scss";
type Vars = CSSProperties & { "--i"?: number; "--n"?: number };
function noise(i: number): number {
const s = Math.sin((i + 1) * 12.9898) * 43758.5453;
return Number((s - Math.floor(s)).toFixed(3));
}
export type TwoToneSweepProps = {
text: string;
/** 스윕 한 주기 (기본 2000ms) */
duration?: number;
base?: string;
sweep?: string;
};
export default function TwoToneSweep({ text, duration = 2000, base = "#17141a", sweep = "#2f6df6" }: TwoToneSweepProps) {
const vars = { "--duration": `${duration}ms`, "--base": base, "--sweep": sweep } as CSSProperties;
const chars = Array.from(text);
const renderLetters = () =>
chars.map((ch, i) => (
<span key={i} className={styles.letter} style={{ "--i": i, "--n": noise(i) } as Vars}>
{ch === " " ? " " : ch}
</span>
));
return (
<div className={styles.sweep} style={vars}>
<span className={styles.base}>{renderLetters()}</span>
<span className={styles.top} aria-hidden="true">{renderLetters()}</span>
</div>
);
}08 Quét hai tông màu — Diện tích đo được 6.474% · khung hình chuyển động 14/23Nguyên tác GODRICH · SCSS và React nằm trong tệp zip · 9 CSS Text Animation Effects — dán 1 dòng là chạy
Bài viết chứa demo này
9 CSS Text Animation Effects — dán 1 dòng là chạyCSS text animation effects là các chuyển động chữ dựng thuần bằng CSS, không cần JavaScript, giúp tiêu đề hay câu chữ xu Xem tất cả demo trong bài này


