05Gõ rồi xoá rồi gõ lại
Một khối keyframes duy nhất cho width chạy 0 sang 100% rồi về 0, gõ một câu, dừng lại một chút rồi xoá, không cần JavaScript.
Dùng choCâu gợi ý trong ô chat trống, placeholder ô tìm kiếm tự động đổi
단일 keyframes0→100%→0hold 구간

<main class="stage">
<p class="search"><span class="search__text">Tìm bất cứ điều gì bạn muốn</span></p>
</main>@use "../../../../site/static/demo-tokens" as *;
$duration: $dur-loop; // 타이핑+삭제 한 루프
$easing: steps(11, end); // 글자 수만큼 뚝뚝 끊어 늘고 준다
$color: $subject-blue; // 커서 색
@include stage($stage-ink);
.search {
margin: 0;
&__text {
display: inline-block;
overflow: hidden;
white-space: nowrap;
width: 0;
border-right: .1em solid $color;
font-weight: 700; font-size: clamp(18px, 5.2vw, 30px); line-height: 1.4; font-family: inherit;
color: $subject-cream;
animation: search-loop $duration linear infinite;
}
}
@keyframes search-loop {
0%, 6% { width: 0; animation-timing-function: $easing; }
46% { width: var(--full, 11ch); }
62% { width: var(--full, 11ch); animation-timing-function: $easing; }
96%, 100% { width: 0; }
}
@media (prefers-reduced-motion: reduce) {
.search__text { animation: none; width: var(--full, 11ch); border-right-color: transparent; }
}html, body {
margin: 0;
overflow: hidden;
}
.stage {
box-sizing: border-box;
min-height: 100vh;
display: grid;
place-items: center;
margin: 0;
background: #17141a;
font-family: -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
padding: clamp(8px, 4vw, 24px);
}
.search {
margin: 0;
}
.search__text {
display: inline-block;
overflow: hidden;
white-space: nowrap;
width: 0;
border-right: 0.1em solid #2f6df6;
font-weight: 700;
font-size: clamp(18px, 5.2vw, 30px);
line-height: 1.4;
font-family: inherit;
color: #fff7e6;
animation: search-loop 2s linear infinite;
}
@keyframes search-loop {
0%, 6% {
width: 0;
animation-timing-function: steps(11, end);
}
46% {
width: var(--full, 11ch);
}
62% {
width: var(--full, 11ch);
animation-timing-function: steps(11, end);
}
96%, 100% {
width: 0;
}
}
@media (prefers-reduced-motion: reduce) {
.search__text {
animation: none;
width: var(--full, 11ch);
border-right-color: transparent;
}
}(function () {
var el = document.querySelector('.search__text'), cv = document.createElement('canvas').getContext('2d');
cv.font = getComputedStyle(el).font;
el.style.setProperty('--full', Math.ceil(cv.measureText(el.textContent).width) + 'px');
})();import { useEffect, useRef } from "react";
import type { CSSProperties } from "react";
import styles from "./DeleteRetype.module.scss";
export type DeleteRetypeProps = {
text: string;
/** 타이핑+삭제 한 루프 (기본 2000ms) */
duration?: number;
color?: string;
};
export default function DeleteRetype({ text, duration = 2000, color = "#2f6df6" }: DeleteRetypeProps) {
const ref = useRef<HTMLSpanElement | null>(null);
useEffect(() => {
const el = ref.current;
const cv = el && document.createElement("canvas").getContext("2d");
if (!el || !cv) return;
cv.font = getComputedStyle(el).font;
el.style.setProperty("--full", Math.ceil(cv.measureText(text).width) + "px");
}, [text]);
const vars = { "--duration": `${duration}ms`, "--color": color, "--easing": `steps(${text.length}, end)` } as CSSProperties;
return (
<p className={styles.search} style={vars}>
<span ref={ref} className={styles.text}>{text}</span>
</p>
);
}05 Gõ rồi xoá rồi gõ lại — Diện tích đo được 3.679% · khung hình chuyển động 18/23Nguyên tác GODRICH · SCSS và React nằm trong tệp zip · 9 kiểu css typing animation, copy dán là chạy
Bài viết chứa demo này
9 kiểu css typing animation, copy dán là chạyCss typing animation là hiệu ứng mô phỏng việc gõ chữ bằng CSS thuần, dựng bằng steps() và một con trỏ nhấp nháy thay ch Xem tất cả demo trong bài này


