Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/react-icons/react-icons/llms.txt

Use this file to discover all available pages before exploring further.

Accessible icons ensure that all users, including those using assistive technologies, can understand and interact with your application effectively.

The Title Prop

The title prop adds a <title> element inside the SVG, providing a text description for screen readers:
import { FaDownload } from "react-icons/fa";

function DownloadButton() {
  return (
    <button>
      <FaDownload title="Download file" />
      Download
    </button>
  );
}
When rendered, this creates:
<svg xmlns="http://www.w3.org/2000/svg">
  <title>Download file</title>
  <!-- icon paths -->
</svg>
The title element provides accessible names for screen readers and appears as a tooltip in many browsers.

Decorative vs Meaningful Icons

Icons fall into two categories that require different accessibility approaches:
Icons that are purely visual and don’t convey unique information should be hidden from screen readers:
import { FaBeer } from "react-icons/fa";

function Question() {
  return (
    <h3>
      Lets go for a <FaBeer aria-hidden="true" />?
    </h3>
  );
}
The text “Lets go for a?” conveys the message, so the icon is decorative.

Icon Buttons

When icons are used as buttons without text, provide accessible labels:
1

Use aria-label

Add descriptive aria-label to the button element:
import { FaSearch } from "react-icons/fa";

function SearchButton() {
  return (
    <button aria-label="Search" onClick={() => {/* search logic */}}>
      <FaSearch />
    </button>
  );
}
2

Add title for tooltips

Optionally include title for visual tooltip:
import { FaSearch } from "react-icons/fa";

function SearchButton() {
  return (
    <button aria-label="Search" title="Search">
      <FaSearch />
    </button>
  );
}
3

Hide icon from screen readers

Add aria-hidden to the icon to avoid redundancy:
import { FaSearch } from "react-icons/fa";

function SearchButton() {
  return (
    <button aria-label="Search">
      <FaSearch aria-hidden="true" />
    </button>
  );
}
import { FaHeart } from "react-icons/fa";

function LikeButton() {
  return (
    <button aria-label="Like this post">
      <FaHeart aria-hidden="true" />
    </button>
  );
}

Icons with Adjacent Text

When icons accompany visible text, hide the icon from screen readers:
import { FaDownload, FaUpload } from "react-icons/fa";

function FileActions() {
  return (
    <div>
      <button>
        <FaDownload aria-hidden="true" style={{ marginRight: '8px' }} />
        Download
      </button>
      <button>
        <FaUpload aria-hidden="true" style={{ marginRight: '8px' }} />
        Upload
      </button>
    </div>
  );
}
Don’t add title or aria-label to decorative icons when text is already present - this creates redundant announcements for screen reader users.
For icon-based navigation links:
import { FaGithub, FaTwitter, FaLinkedin } from "react-icons/fa";

function SocialLinks() {
  return (
    <nav aria-label="Social media links">
      <a 
        href="https://github.com/username" 
        aria-label="GitHub profile"
        target="_blank"
        rel="noopener noreferrer"
      >
        <FaGithub aria-hidden="true" />
      </a>
      <a 
        href="https://twitter.com/username" 
        aria-label="Twitter profile"
        target="_blank"
        rel="noopener noreferrer"
      >
        <FaTwitter aria-hidden="true" />
      </a>
      <a 
        href="https://linkedin.com/in/username" 
        aria-label="LinkedIn profile"
        target="_blank"
        rel="noopener noreferrer"
      >
        <FaLinkedin aria-hidden="true" />
      </a>
    </nav>
  );
}

Status Indicators

For icons indicating status, ensure the meaning is conveyed accessibly:
import { FaCheckCircle, FaTimesCircle, FaSpinner } from "react-icons/fa";

function StatusMessage({ status, message }) {
  const icons = {
    success: FaCheckCircle,
    error: FaTimesCircle,
    loading: FaSpinner
  };
  
  const Icon = icons[status];
  
  return (
    <div role="status" aria-live="polite">
      <Icon aria-hidden="true" />
      <span>{message}</span>
    </div>
  );
}

Form Field Icons

Icons in form fields require special consideration:
import { FaUser, FaLock, FaEnvelope } from "react-icons/fa";

function LoginForm() {
  return (
    <form>
      <div>
        <label htmlFor="username">
          <FaUser aria-hidden="true" />
          Username
        </label>
        <input id="username" type="text" />
      </div>
      
      <div>
        <label htmlFor="email">
          <FaEnvelope aria-hidden="true" />
          Email
        </label>
        <input id="email" type="email" />
      </div>
      
      <div>
        <label htmlFor="password">
          <FaLock aria-hidden="true" />
          Password
        </label>
        <input id="password" type="password" />
      </div>
    </form>
  );
}
Always pair form field icons with visible labels. Icons alone are not sufficient for accessibility.

Icon-Based Navigation

For icon-heavy navigation, provide multiple ways to understand the interface:
import { FaHome, FaUser, FaCog, FaBell } from "react-icons/fa";

function TabNavigation() {
  return (
    <nav aria-label="Main navigation">
      <ul role="tablist">
        <li role="presentation">
          <button role="tab" aria-selected="true" aria-label="Home">
            <FaHome aria-hidden="true" />
            <span>Home</span>
          </button>
        </li>
        <li role="presentation">
          <button role="tab" aria-selected="false" aria-label="Profile">
            <FaUser aria-hidden="true" />
            <span>Profile</span>
          </button>
        </li>
        <li role="presentation">
          <button role="tab" aria-selected="false" aria-label="Settings">
            <FaCog aria-hidden="true" />
            <span>Settings</span>
          </button>
        </li>
        <li role="presentation">
          <button role="tab" aria-selected="false" aria-label="Notifications">
            <FaBell aria-hidden="true" />
            <span>Notifications</span>
          </button>
        </li>
      </ul>
    </nav>
  );
}

Color and Contrast

Never rely on color alone to convey information. Icons should be distinguishable by shape, not just color.
Ensure icons meet WCAG contrast requirements:
import { FaExclamationTriangle, FaInfoCircle } from "react-icons/fa";

function Alerts() {
  return (
    <div>
      {/* ✓ Good: Combines color with icon shape and text */}
      <div role="alert">
        <FaExclamationTriangle 
          aria-hidden="true" 
          color="#dc2626" 
        />
        <span>Error: Please check your input</span>
      </div>
      
      {/* ✓ Good: High contrast, distinctive shape */}
      <div role="status">
        <FaInfoCircle 
          aria-hidden="true" 
          color="#2563eb" 
        />
        <span>Info: Your changes have been saved</span>
      </div>
    </div>
  );
}

Accessibility Checklist

✓ Add aria-hidden="true"✓ Ensure adjacent text provides full context✓ Don’t add title or aria-label
✓ Add aria-label to the parent interactive element✓ Or provide visible text label✓ Consider adding title for tooltips✓ Add aria-hidden="true" to avoid redundancy when label is present
✓ Use role="status" or role="alert"✓ Consider aria-live regions for dynamic updates✓ Include text description, not just the icon
✓ Ensure 3:1 contrast ratio for UI components (WCAG AA)✓ Don’t rely on color alone to convey meaning✓ Test with color blindness simulators

Testing Accessibility

Test your icon implementation with:
  • Screen readers: NVDA (Windows), JAWS (Windows), VoiceOver (macOS/iOS)
  • Keyboard navigation: Ensure all icon buttons are keyboard accessible
  • Browser extensions: axe DevTools, WAVE, Lighthouse
  • Automated testing: jest-axe, pa11y, Playwright accessibility tests
// Example: Testing with jest-axe
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
import { FaDownload } from 'react-icons/fa';

expect.extend(toHaveNoViolations);

test('download button is accessible', async () => {
  const { container } = render(
    <button aria-label="Download file">
      <FaDownload aria-hidden="true" />
    </button>
  );
  
  const results = await axe(container);
  expect(results).toHaveNoViolations();
});

Next Steps

Customizing Icons

Learn how to customize icon appearance

Styling

Apply global styles with IconContext