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:
Decorative Icons
Meaningful Icons
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. Icons that convey information not present in text need accessible labels: 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.
When icons are used as buttons without text, provide accessible labels:
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 >
);
}
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 >
);
}
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 >
);
}
Icon-Only Button (Good)
Icon-Only Button (Bad)
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.
Interactive Icon Links
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:
With ARIA Live Region
With Visually Hidden Text
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 >
);
}
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
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
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
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
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
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