The blink element is obsolete: the HTML standard lists it as non-conforming and says to use CSS instead, and current browsers show its text as plain, still text. To make something blink today, write a CSS keyframes animation, stop it after a few cycles or give people a pause control, and switch it off under prefers-reduced-motion.
| Old way | Status | Use instead |
|---|---|---|
| <blink>text</blink> | Obsolete, non-conforming | A CSS animation on a span |
| text-decoration: blink | Deprecated; browsers may not blink | @keyframes changing opacity |
| <marquee> | Obsolete, non-conforming | CSS transitions or animations |
| Endless blinking | Fails WCAG 2.2.2 after five seconds without a pause | A cycle limit or a pause button |
Updated
The blink tag is a piece of web history that still gets searched for, usually by someone who wants a status dot, a cursor or a sale badge to flash. The builder below makes that effect the modern way and keeps it inside the accessibility rules, so the motion is short, can be stopped, and respects the visitor's settings.
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0.15; }
}
.blink {
animation: blink 1000ms ease-in-out 3;
}
.blink.is-paused {
animation-play-state: paused;
}
@media (prefers-reduced-motion: reduce) {
.blink { animation: none; }
}Three one-second cycles end well inside five seconds, so no pause control is needed. Reload the frame by editing the code.
<style>
@keyframes blink { 0%, 100% { opacity: 1 } 50% { opacity: .15 } }
.dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%;
background: #16a34a; animation: blink 1s ease-in-out 3; }
@media (prefers-reduced-motion: reduce) { .dot { animation: none } }
</style>
<p><span class="dot"></span> Store is open</p>steps(1, end) switches instantly instead of fading. The caret is decorative, so it is hidden from screen readers.
<style>
@keyframes caret { 50% { border-color: transparent } }
.type { font: 18px monospace; border-right: 2px solid #111; padding-right: 2px;
animation: caret 1s steps(1, end) infinite; }
@media (prefers-reduced-motion: reduce) { .type { animation: none } }
</style>
<p><span class="type">npm run dev</span></p>Browsers draw the content of an obsolete blink element as ordinary text. Nothing flashes.
<p>Sale ends <blink>tonight</blink>.</p>If the blinking has to run for longer than five seconds, give it a real button that stops it.
aria-pressed tells assistive technology whether the animation is currently paused.
const btn = document.querySelector("#pause-blink");
const el = document.querySelector(".blink");
btn.addEventListener("click", () => {
const paused = el.classList.toggle("is-paused");
btn.setAttribute("aria-pressed", String(paused));
});
Flashing text pulls attention away from everything else on the page and is hard to read while it is invisible half the time. For people with attention or vestibular conditions it can make a page unusable, which is why the standards moved blinking out of HTML and into CSS, where it can be controlled.
The effect itself is not banned. What matters is how long it runs, how fast it flashes and whether people can stop it.
First, keyframes that change opacity, which renders smoothly. Second, a finite iteration count or a visible pause control. Third, a reduced-motion override that leaves the element steady.
The animation-play-state property makes a pause button simple: toggle a class that sets it to paused, and the element freezes where it is.
No current browser makes it flash. The HTML standard treats blink as an obsolete, non-conforming element, so its content renders as ordinary inline text. Validators flag it as an error.
The blink value of text-decoration-line is deprecated, and the specification allows browsers not to blink the text at all. A keyframes animation is the reliable replacement.
WCAG 2.2.2 Pause, Stop, Hide is a Level A rule: blinking that starts automatically, lasts more than five seconds and sits beside other content needs a way to pause, stop or hide it. Separately, 2.3.1 limits flashing to three times in any one second.
Animate a thin border or a pipe character with steps(1) so it switches between visible and hidden, at about one cycle per second. A caret in a typing demo is decorative, so give it aria-hidden="true".
Wrap an override in @media (prefers-reduced-motion: reduce) and set animation: none on the blinking element. The media feature is widely supported and follows the motion setting in the visitor's operating system.
Related: CSS animation generator, CSS transitions playground, WCAG checklist, Website accessibility checklist, HTML and CSS cheat sheet.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.