> ## 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.

# Accessibility

> Make your React Icons accessible with proper ARIA attributes and semantic HTML

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:

```jsx theme={null}
import { FaDownload } from "react-icons/fa";

function DownloadButton() {
  return (
    <button>
      <FaDownload title="Download file" />
      Download
    </button>
  );
}
```

When rendered, this creates:

```html theme={null}
<svg xmlns="http://www.w3.org/2000/svg">
  <title>Download file</title>
  <!-- icon paths -->
</svg>
```

<Tip>
  The `title` element provides accessible names for screen readers and appears as a tooltip in many browsers.
</Tip>

## Decorative vs Meaningful Icons

Icons fall into two categories that require different accessibility approaches:

<Tabs>
  <Tab title="Decorative Icons">
    Icons that are purely visual and don't convey unique information should be hidden from screen readers:

    ```jsx theme={null}
    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.
  </Tab>

  <Tab title="Meaningful Icons">
    Icons that convey information not present in text need accessible labels:

    ```jsx theme={null}
    import { FaTrash, FaEdit } from "react-icons/fa";

    function Actions() {
      return (
        <div>
          <button aria-label="Delete item">
            <FaTrash />
          </button>
          <button aria-label="Edit item">
            <FaEdit />
          </button>
        </div>
      );
    }
    ```

    Without text labels, these buttons need `aria-label` to be accessible.
  </Tab>
</Tabs>

## Icon Buttons

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

<Steps>
  <Step title="Use aria-label">
    Add descriptive `aria-label` to the button element:

    ```jsx theme={null}
    import { FaSearch } from "react-icons/fa";

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

  <Step title="Add title for tooltips">
    Optionally include `title` for visual tooltip:

    ```jsx theme={null}
    import { FaSearch } from "react-icons/fa";

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

  <Step title="Hide icon from screen readers">
    Add `aria-hidden` to the icon to avoid redundancy:

    ```jsx theme={null}
    import { FaSearch } from "react-icons/fa";

    function SearchButton() {
      return (
        <button aria-label="Search">
          <FaSearch aria-hidden="true" />
        </button>
      );
    }
    ```
  </Step>
</Steps>

<CodeGroup>
  ```jsx Icon-Only Button (Good) theme={null}
  import { FaHeart } from "react-icons/fa";

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

  ```jsx Icon-Only Button (Bad) theme={null}
  import { FaHeart } from "react-icons/fa";

  function LikeButton() {
    // ❌ No accessible label - screen readers can't describe this button
    return (
      <button>
        <FaHeart />
      </button>
    );
  }
  ```
</CodeGroup>

## Icons with Adjacent Text

When icons accompany visible text, hide the icon from screen readers:

```jsx theme={null}
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>
  );
}
```

<Warning>
  Don't add `title` or `aria-label` to decorative icons when text is already present - this creates redundant announcements for screen reader users.
</Warning>

## Interactive Icon Links

For icon-based navigation links:

```jsx theme={null}
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:

<CodeGroup>
  ```jsx With ARIA Live Region theme={null}
  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>
    );
  }
  ```

  ```jsx With Visually Hidden Text theme={null}
  import { FaCheckCircle } from "react-icons/fa";

  function SuccessIcon() {
    return (
      <span>
        <FaCheckCircle aria-hidden="true" color="green" />
        <span className="sr-only">Success</span>
      </span>
    );
  }

  // CSS
  // .sr-only {
  //   position: absolute;
  //   width: 1px;
  //   height: 1px;
  //   padding: 0;
  //   margin: -1px;
  //   overflow: hidden;
  //   clip: rect(0, 0, 0, 0);
  //   white-space: nowrap;
  //   border-width: 0;
  // }
  ```
</CodeGroup>

## Form Field Icons

Icons in form fields require special consideration:

```jsx theme={null}
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>
  );
}
```

<Tip>
  Always pair form field icons with visible labels. Icons alone are not sufficient for accessibility.
</Tip>

## Icon-Based Navigation

For icon-heavy navigation, provide multiple ways to understand the interface:

```jsx theme={null}
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

<Warning>
  Never rely on color alone to convey information. Icons should be distinguishable by shape, not just color.
</Warning>

Ensure icons meet WCAG contrast requirements:

```jsx theme={null}
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

<AccordionGroup>
  <Accordion title="Is the icon decorative?">
    ✓ Add `aria-hidden="true"`

    ✓ Ensure adjacent text provides full context

    ✓ Don't add `title` or `aria-label`
  </Accordion>

  <Accordion title="Is the icon meaningful/functional?">
    ✓ 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
  </Accordion>

  <Accordion title="Is the icon in a button or link?">
    ✓ Ensure the button/link has an accessible name

    ✓ Use `aria-label` if no visible text

    ✓ Add `aria-hidden="true"` to the icon
  </Accordion>

  <Accordion title="Does the icon convey status?">
    ✓ Use `role="status"` or `role="alert"`

    ✓ Consider `aria-live` regions for dynamic updates

    ✓ Include text description, not just the icon
  </Accordion>

  <Accordion title="Does the icon meet contrast requirements?">
    ✓ Ensure 3:1 contrast ratio for UI components (WCAG AA)

    ✓ Don't rely on color alone to convey meaning

    ✓ Test with color blindness simulators
  </Accordion>
</AccordionGroup>

## 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

```jsx theme={null}
// 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

<CardGroup cols={2}>
  <Card title="Customizing Icons" icon="sliders" href="/guides/customizing-icons">
    Learn how to customize icon appearance
  </Card>

  <Card title="Styling" icon="paintbrush" href="/guides/styling">
    Apply global styles with IconContext
  </Card>
</CardGroup>
