Text✨ Premium

Blur Reveal

Pure CSS animation that transitions text from blurry and invisible to sharp and readable — duration, blur intensity, and easing are fully adjustable.

CSSBlurReveal

You'll get access to the interactive demo with a free account.

This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Text has 56 effects, including 4 free. Explore the category →

3 usage examples

Portfolio / Landing — Identity name or headline revealed on load — Blur Reveal example 1

① Portfolio / Landing — Identity name or headline revealed on load

WhenOn arrival at a portfolio or landing page, when the name or main headline is the first element the eye should encounter.
WhyThe unblur creates a cinematic entrance without an animation library — the name seems to materialize in front of the visitor, strengthening the first impression without gimmicky animation.
SettingsInitial blur: blur(16px), duration: 1.4s, timing: ease-out, delay: 0.3s. For multiple lines, offset the delay by 0.2s per element.
Article headline — Scripted entrance on scroll or scene transition — Blur Reveal example 2

② Article headline — Scripted entrance on scroll or scene transition

WhenWhen a full-screen illustration gives way to the article title, or when the user scrolls to a key section of a long-form piece.
WhyThe blur-to-sharp transition mimics a camera lens pulling focus — a common motion design aesthetic in editorial work that lends authority to the headline without gimmicky animation.
SettingsInitial blur: blur(24px), duration: 1.8s, timing: ease-out, 4–6 rem type, letter-spacing: -0.04em. Trigger via IntersectionObserver by adding the class as the element enters the viewport.
KPI reveal — Calculated result in a dashboard — Blur Reveal example 3

③ KPI reveal — Calculated result in a dashboard

WhenWhen a key figure (revenue, score, unit count) has just been received from the API and is displayed for the first time in the interface.
WhyUnblurring a number visually signals that the value was just calculated — the user perceives the figure as fresh and accurate, reducing doubt about its recency.
SettingsInitial blur: blur(8px), duration: 0.6s, timing: ease, 200ms delay after data reception. Apply only to the number (<span> child), not the whole card.

How it works

The animation is driven entirely by CSS via @keyframes blurReveal. The initial state of .text-blur-reveal combines filter: blur(10px) and opacity: 0 — text is blurry and invisible. The to keyframe brings both values to filter: blur(0) and opacity: 1. The simultaneous interpolation of both properties creates the impression of text gradually emerging from a fog.

The forwards keyword in the animation shorthand is essential: it preserves the last keyframe state (blur(0), opacity: 1) once the duration has elapsed. Without it, the browser would instantly revert the text to its initial state (blur(10px), opacity: 0) at the end of the animation.

To replay the animation on click, the standard vanilla JS technique is to remove the .text-blur-reveal class, read element.offsetWidth (forces a browser reflow), then re-add the class: the cycle restarts cleanly from keyframe 0. No library needed — two lines of code.

Accessibility

  • prefers-reduced-motion not implemented: the base version does not detect the system preference. Add @media (prefers-reduced-motion: reduce) { .text-blur-reveal { animation: none; filter: none; opacity: 1; } } to display the text immediately without animation.
  • The text stays in the DOM and accessibility tree throughout the animation — filter and opacity do not affect screen reader output.
  • opacity: 0 in the initial state hides the text visually but is not equivalent to visibility: hidden or display: none: the content is already accessible to AT from page load.
  • At the final state (filter: blur(0), opacity: 1), the effect does not alter any contrast ratio — WCAG AA compliance depends solely on the chosen colors.
  • If a 'Replay' button is exposed to the user, wire it to a native focusable <button>, not a clickable div — the keyboard must be able to trigger the replay.

Browser compatibility

CSS filter: blur() and @keyframes are supported in all modern browsers. Zero JS dependency for the base animation.

Chrome 88+✓ Full
Firefox 87+✓ Full
Safari 15.4+✓ Full
Edge 88+✓ Full
Mobile iOS✓ Full
Android Chrome✓ Full

Without <code>filter</code> support (IE 11), the animation retains only the opacity transition (0 → 1) — the text fades in without blur. Without <code>@keyframes</code> at all, the text remains invisible (<code>opacity: 0</code>): add <code>.text-blur-reveal { opacity: 1; animation: none; }</code> as a fallback rule to protect that case.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
<div class="demo-preview">
  <!-- Single text -->
  <span class="demo-text text-blur-reveal">Your text</span>
</div>

<!-- Multiple lines with staggered delay -->
<div class="demo-preview">
  <span class="demo-text text-blur-reveal">Headline</span>
  <span class="demo-text text-blur-reveal"
        style="animation-delay: 0.3s">Subheadline</span>
</div>
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
blur(10px) in .text-blur-reveal 10px Starting blur intensity. 4px = subtle, 10px = standard, 24px = dramatic. Change the value in the initial state of the selector (not in the keyframe, which already targets blur(0)).
animation: 1s ease in .text-blur-reveal 1s ease Duration and timing. Replace 1s with the target value (0.5s = snappy, 1.8s = cinematic); ease-out for elegant deceleration, linear for a constant unblur rate.
0s (delay) in the animation shorthand 0s Delay before triggering. Set to 0.3s to let the page render before animating, or override per element via style="animation-delay: Xs" for staggered reveals.
opacity: 0 in .text-blur-reveal 0 Starting opacity. Set to 0.3 for a semi-visible start (text faintly perceptible on frame 1 — softer effect, less visual jump).
font-size: 2.5rem in .demo-text 2.5rem Text size — the animation adapts to any size. 1rem for a label, 6rem for a hero headline.
letter-spacing: -.02em in .demo-text -0.02em Letter spacing. Negative value for large headings (condensed look), 0 or slightly positive for body text.

FAQ

Remove the .text-blur-reveal class from the element, read element.offsetWidth (forces a browser reflow), then re-add the class: el.classList.remove('text-blur-reveal'); void el.offsetWidth; el.classList.add('text-blur-reveal');. The browser restarts cleanly from keyframe 0 — two lines of JS, zero dependencies.
Yes. Do not add the .text-blur-reveal class in HTML (or remove it on load via JS), then apply it inside an IntersectionObserver callback when isIntersecting becomes true: the animation fires at the exact moment the element becomes visible, without polling.
Wrap each line in a <span class="text-blur-reveal"> and override the delay inline: style="animation-delay: 0.2s", style="animation-delay: 0.4s", and so on. Elements unblur in a cascade with no extra JS.