Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/recharts/recharts/llms.txt

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

Accessible charts ensure that all users, including those using assistive technologies, can understand your data. This guide covers accessibility best practices for Recharts.

Semantic structure

Provide descriptive titles

Always add a title that describes what the chart shows:
function AccessibleChart() {
  return (
    <div>
      <h2 id="chart-title">Monthly Revenue 2024</h2>
      <LineChart
        width={600}
        height={300}
        data={data}
        aria-labelledby="chart-title"
      >
        <XAxis dataKey="month" />
        <YAxis />
        <Line dataKey="revenue" stroke="#8884d8" />
      </LineChart>
    </div>
  );
}

Add descriptive labels

Use ARIA labels for context:
<LineChart
  width={600}
  height={300}
  data={data}
  aria-label="Line chart showing monthly revenue from January to December 2024"
  role="img"
>
  {/* ... */}
</LineChart>

Animation accessibility

Respect motion preferences

Recharts automatically respects the user’s prefers-reduced-motion setting when using isAnimationActive="auto":
<Line
  dataKey="value"
  isAnimationActive="auto"  {/* Respects prefers-reduced-motion */}
/>
This is the recommended approach for all animations.

Provide animation controls

For critical visualizations, offer users control:
function AccessibleAnimatedChart() {
  const [animate, setAnimate] = useState(true);
  
  return (
    <div>
      <button onClick={() => setAnimate(!animate)}>
        {animate ? 'Disable' : 'Enable'} Animations
      </button>
      <LineChart width={600} height={300} data={data}>
        <Line
          dataKey="value"
          isAnimationActive={animate}
        />
      </LineChart>
    </div>
  );
}

Color and contrast

Ensure sufficient contrast

Use colors with WCAG AA compliant contrast ratios (at least 4.5:1 for text, 3:1 for UI components):
{/* ❌ Low contrast */}
<Line dataKey="value" stroke="#ccc" />

{/* ✅ Good contrast */}
<Line dataKey="value" stroke="#0066cc" />

Don’t rely on color alone

Use patterns, shapes, or labels in addition to color:
function AccessibleMultiSeriesChart() {
  return (
    <LineChart width={600} height={300} data={data}>
      <XAxis dataKey="month" />
      <YAxis />
      <Legend />
      {/* Different stroke styles */}
      <Line
        dataKey="revenue"
        stroke="#8884d8"
        strokeWidth={2}
        name="Revenue"
      />
      <Line
        dataKey="profit"
        stroke="#82ca9d"
        strokeDasharray="5 5"
        strokeWidth={2}
        name="Profit"
      />
      <Line
        dataKey="cost"
        stroke="#ffc658"
        strokeDasharray="3 3"
        strokeWidth={2}
        name="Cost"
      />
    </LineChart>
  );
}

Use accessible color palettes

Choose colorblind-friendly palettes:
// Example: Colorblind-safe palette
const colors = {
  blue: '#0173B2',
  orange: '#DE8F05',
  green: '#029E73',
  red: '#CC78BC',
  purple: '#CA9161',
};

<BarChart data={data}>
  <Bar dataKey="category1" fill={colors.blue} />
  <Bar dataKey="category2" fill={colors.orange} />
  <Bar dataKey="category3" fill={colors.green} />
</BarChart>

Tooltips and interaction

Keyboard-accessible tooltips

Recharts tooltips are keyboard accessible by default. Ensure custom tooltips maintain this:
const AccessibleTooltip = ({ active, payload, label }) => {
  if (!active || !payload) return null;
  
  return (
    <div
      style={{
        backgroundColor: 'white',
        padding: '12px',
        border: '1px solid #ccc',
      }}
      role="tooltip"
      aria-live="polite"
    >
      <p style={{ margin: 0, fontWeight: 'bold' }}>{label}</p>
      {payload.map((entry, index) => (
        <p key={index} style={{ margin: 0, color: entry.color }}>
          {entry.name}: {entry.value}
        </p>
      ))}
    </div>
  );
};

<Tooltip content={<AccessibleTooltip />} />

Focus indicators

Ensure interactive elements have visible focus states:
<LineChart data={data}>
  <Line
    dataKey="value"
    stroke="#8884d8"
    activeDot={{
      r: 8,
      stroke: '#0066cc',
      strokeWidth: 2,
      fill: 'white',
    }}
  />
</LineChart>

Alternative text representations

Provide data tables

Offer a table version for screen reader users:
function ChartWithTable({ data }) {
  const [showTable, setShowTable] = useState(false);
  
  return (
    <div>
      <button onClick={() => setShowTable(!showTable)}>
        {showTable ? 'Show Chart' : 'Show Data Table'}
      </button>
      
      {showTable ? (
        <table>
          <caption>Monthly Revenue Data</caption>
          <thead>
            <tr>
              <th>Month</th>
              <th>Revenue</th>
            </tr>
          </thead>
          <tbody>
            {data.map((item, index) => (
              <tr key={index}>
                <td>{item.month}</td>
                <td>${item.revenue.toLocaleString()}</td>
              </tr>
            ))}
          </tbody>
        </table>
      ) : (
        <LineChart width={600} height={300} data={data}>
          <XAxis dataKey="month" />
          <YAxis />
          <Line dataKey="revenue" stroke="#8884d8" />
        </LineChart>
      )}
    </div>
  );
}

Add text descriptions

Provide a text summary of key insights:
function DescribedChart({ data }) {
  const maxRevenue = Math.max(...data.map(d => d.revenue));
  const minRevenue = Math.min(...data.map(d => d.revenue));
  
  return (
    <div>
      <h2>Monthly Revenue</h2>
      <p id="chart-description">
        This chart shows monthly revenue throughout 2024.
        Revenue ranged from ${minRevenue.toLocaleString()} to ${maxRevenue.toLocaleString()}.
      </p>
      <LineChart
        width={600}
        height={300}
        data={data}
        aria-describedby="chart-description"
      >
        <XAxis dataKey="month" />
        <YAxis />
        <Line dataKey="revenue" stroke="#8884d8" />
      </LineChart>
    </div>
  );
}

Axis accessibility

Label your axes

Always label axes clearly:
<LineChart width={600} height={300} data={data}>
  <XAxis
    dataKey="month"
    label={{ value: 'Month', position: 'insideBottom', offset: -5 }}
  />
  <YAxis
    label={{ value: 'Revenue ($)', angle: -90, position: 'insideLeft' }}
  />
  <Line dataKey="revenue" stroke="#8884d8" />
</LineChart>

Format tick labels

Make tick values readable:
<YAxis
  tickFormatter={(value) => `$${value.toLocaleString()}`}
/>

<XAxis
  dataKey="date"
  tickFormatter={(value) => new Date(value).toLocaleDateString()}
/>

Legend accessibility

Ensure legends are readable

<Legend
  wrapperStyle={{
    fontSize: '14px',
    color: '#333',
  }}
  iconSize={18}
/>

Provide context in legend labels

<Line
  dataKey="revenue"
  name="Monthly Revenue (USD)"
  stroke="#8884d8"
/>
<Line
  dataKey="profit"
  name="Net Profit (USD)"
  stroke="#82ca9d"
/>

Responsive design

Adapt to different screen sizes

function ResponsiveAccessibleChart() {
  const isMobile = window.innerWidth < 768;
  
  return (
    <ResponsiveContainer width="100%" height={isMobile ? 300 : 400}>
      <LineChart data={data}>
        <XAxis
          dataKey="month"
          angle={isMobile ? -45 : 0}
          textAnchor={isMobile ? 'end' : 'middle'}
          height={isMobile ? 80 : 30}
        />
        <YAxis width={isMobile ? 40 : 60} />
        <Tooltip />
        <Legend
          layout={isMobile ? 'horizontal' : 'vertical'}
          align={isMobile ? 'center' : 'right'}
        />
        <Line dataKey="value" stroke="#8884d8" />
      </LineChart>
    </ResponsiveContainer>
  );
}

Support text scaling

Use relative units for text:
<XAxis
  tick={{ fontSize: '0.875rem' }}  {/* Instead of 14 */}
/>

Testing accessibility

Screen reader testing

  1. Test with NVDA (Windows), JAWS (Windows), or VoiceOver (macOS)
  2. Navigate using keyboard only (Tab, Arrow keys)
  3. Verify all information is announced

Automated testing

Use tools like:

Manual checks

  • Can you navigate to all interactive elements with keyboard?
  • Are focus indicators visible?
  • Do tooltips work without a mouse?
  • Is color contrast sufficient?
  • Are animations respectful of motion preferences?
  • Is there alternative text representation?

ARIA attributes reference

Essential ARIA attributes for charts

<LineChart
  width={600}
  height={300}
  data={data}
  role="img"
  aria-label="Descriptive label"
  aria-labelledby="chart-title"  {/* Reference to title element */}
  aria-describedby="chart-desc"   {/* Reference to description */}
>
  {/* ... */}
</LineChart>

Best practices checklist

Core accessibility principles
  • ✅ Provide text alternatives (titles, labels, descriptions)
  • ✅ Use sufficient color contrast
  • ✅ Don’t rely on color alone
  • ✅ Make interactive elements keyboard accessible
  • ✅ Respect motion preferences
  • ✅ Support responsive design and text scaling
  • ✅ Test with assistive technologies
Common pitfalls
  • ❌ Missing axis labels
  • ❌ Low color contrast
  • ❌ Forced animations that can’t be disabled
  • ❌ No alternative to visual representation
  • ❌ Small touch targets on mobile
  • ❌ Unlabeled data series
WCAG compliance levels
  • Level A: Basic accessibility (minimum)
  • Level AA: Recommended for most sites (includes 4.5:1 contrast)
  • Level AAA: Enhanced accessibility (includes 7:1 contrast)
Aim for at least WCAG 2.1 Level AA compliance.

Resources