CSS Tutorial menu

CSS for Accessibility

Accessible CSS makes your site usable by everyone, including people who use a keyboard, have weak eyesight, or feel ill from moving screens.

Why It Matters

Many visitors do not use a mouse. Some use only the keyboard, some use screen readers, and some zoom the page to 200%. Good CSS helps all of them, and it also helps everyone else: big buttons are easier to tap on a bumpy bus ride, too.

Never Remove Focus Without a Replacement

When you press Tab, the browser shows a ring around the focused link or button. Keyboard users need it to know where they are. A very common mistake is:

Example

css
/* Bad: keyboard users are now lost */
button:focus {
  outline: none;
}

:focus-visible

Designers sometimes dislike the ring appearing after a mouse click. :focus-visible solves this. The browser shows it when focus should be visible, such as when using the keyboard, and usually not after a mouse click on a button.

Example

html
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 20px; }
a, button {
  font-size: 1rem;
  margin-right: 10px;
}
button {
  background-color: #264de4;
  color: white;
  border: none;
  padding: 10px 18px;
  border-radius: 6px;
}
:focus-visible {
  outline: 3px solid #f97316;
  outline-offset: 3px;
}
</style>
</head>
<body>

<p>Click inside the page, then press the Tab key several times.</p>
<a href="#">Courses</a>
<button>Register</button>
<button>Contact</button>

</body>
</html>
Try it Yourself »

Clicking a button with the mouse shows no ring. Pressing Tab shows a clear orange ring with a small gap.

Use outline for focus styles, not border. An outline does not change the size of the element, so nothing jumps around when focus moves.

Respecting Reduced Motion

Some people get dizzy or sick from animations, parallax and smooth scrolling. They can switch on "Reduce motion" in their phone or computer settings. CSS can read this with prefers-reduced-motion.

QueryMatches when
@media (prefers-reduced-motion: reduce)The user asked for less motion
@media (prefers-reduced-motion: no-preference)The user has not asked

The safest pattern is to add motion only for people who have not asked for less:

Example

html
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 20px; }
.badge {
  display: inline-block;
  background-color: crimson;
  color: white;
  padding: 8px 14px;
  border-radius: 20px;
}
@keyframes bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-10px); }
}
@media (prefers-reduced-motion: no-preference) {
  .badge {
    animation: bounce 1s ease-in-out infinite;
  }
  html {
    scroll-behavior: smooth;
  }
}
</style>
</head>
<body>

<span class="badge">Admissions open</span>
<p>Turn on "Reduce motion" in your device settings and run this again: the badge stops bouncing.</p>

</body>
</html>
Try it Yourself »

A short way to switch off almost all motion on an existing site:

Example

css
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

Colour Contrast

Text must stand out clearly from its background. The WCAG guidelines ask for a contrast ratio of at least:

TextMinimum ratio
Normal text4.5 : 1
Large text (about 24px, or 19px bold)3 : 1
Icons and input borders3 : 1

Light grey text on a white background often fails. Browser developer tools (F12) show the contrast ratio when you inspect a colour.

Never show meaning with colour alone. A red border for an error is not enough for colour-blind users. Add an icon or a message such as "Email is required".

Readable Text and Zoom

  • Use rem for font sizes so the user's browser font setting is respected (see CSS Units)
  • Keep body text at least 1rem (16px)
  • Use line-height of about 1.5 for paragraphs
  • Limit line length with max-width: 65ch
  • Never block zooming in the viewport meta tag (do not use user-scalable=no)

Bigger Tap Targets

Small links are hard to tap, especially for older people. Aim for buttons and links at least 44 by 44 pixels.

Example

css
.icon-button {
  min-width: 44px;
  min-height: 44px;
}

Visually Hidden Text

Sometimes a button shows only an icon, like a search glass. Screen readers still need a text label. This common class hides text on screen but keeps it for screen readers:

Example

css
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

Example

html
<button><span aria-hidden="true">🔍</span><span class="visually-hidden">Search</span></button>

Do not use display: none for this, because it hides the text from screen readers too.

Exercise

Exercise

Which media query lets you turn off animations for users who asked their device for less motion?

Learn CSS with a teacher

Join the Web Development course at Workownix, online or in Orangi Town, Karachi, and get a certificate.

See the course Ask on WhatsApp