描边文字填充
悬停时镂空的描边文字从下往上被填满颜色,像液体在字里慢慢上升。
用纯 CSS 制作悬停时被填满的描边文字。文字设为 color: transparent,并用 -webkit-text-stroke: 1.5px(浅色文字色)描边。上面叠一层 ::after,content: attr(data-text),以主色实心填充,并设为 clip-path: inset(100% 0 0 0) 隐藏。在 :hover 和 :focus-visible 时,把 clip-path 在 500ms 内过渡到 inset(0 0 0 0),缓动 cubic-bezier(0.16, 1, 0.3, 1),让颜色从基线升起。使用粗体展示字体,让描边清晰可读。真实文字放在视觉隐藏的 span 中,视觉元素设为 aria-hidden。在 prefers-reduced-motion 下直接切换到填满状态。文字为“探索更多”。
源代码
'use client'
import s from './demo.module.css'
export default function OutlineFill({ labels }: { labels: Record<string, string> }) {
return (
<a href="#" className={s.link} onClick={(e) => e.preventDefault()}>
<span className={s.sr}>{labels.text}</span>
<span className={s.word} data-text={labels.text} aria-hidden="true">
{labels.text}
</span>
</a>
)
}
.link {
border-radius: 6px;
text-decoration: none;
}
.link:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 6px; }
.sr {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.word {
position: relative;
display: inline-block;
font: 800 clamp(2.4rem, 9vw, 3.4rem) / 1.1 var(--font-display);
letter-spacing: -0.01em;
color: transparent;
-webkit-text-stroke: 1.5px var(--stage-ink);
}
.word::after {
content: attr(data-text);
position: absolute;
inset: 0;
color: var(--stage-accent);
-webkit-text-stroke: 1.5px var(--stage-accent);
clip-path: inset(100% 0 0 0);
transition: clip-path 500ms var(--ease-out);
}
.link:hover .word::after,
.link:focus-visible .word::after { clip-path: inset(0 0 0 0); }
@media (prefers-reduced-motion: reduce) {
.word::after { transition: none; }
}