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.

Recharts provides powerful tools for creating responsive visualizations that adapt to different screen sizes and container dimensions. The ResponsiveContainer component is the foundation of responsive chart design.

ResponsiveContainer

The ResponsiveContainer component automatically adjusts chart dimensions based on its parent container size.

Basic usage

import { ResponsiveContainer, LineChart, Line, XAxis, YAxis } from 'recharts';

function ResponsiveChart() {
  return (
    <div style={{ width: '100%', height: 400 }}>
      <ResponsiveContainer>
        <LineChart data={data}>
          <XAxis dataKey="name" />
          <YAxis />
          <Line dataKey="value" stroke="#8884d8" />
        </LineChart>
      </ResponsiveContainer>
    </div>
  );
}
The parent container of ResponsiveContainer must have a defined width and height. ResponsiveContainer fills 100% of its parent by default.

How it works

The ResponsiveContainer component:
  1. Observes its parent container using the ResizeObserver API
  2. Calculates appropriate dimensions based on container size
  3. Provides these dimensions to child charts via React context
  4. Re-renders charts when container size changes
// From src/component/ResponsiveContainer.tsx:170-199
useEffect(() => {
  if (containerRef.current == null || typeof ResizeObserver === 'undefined') {
    return noop;
  }
  let callback = (entries: ResizeObserverEntry[]) => {
    const entry = entries[0];
    if (entry == null) {
      return;
    }
    const { width: containerWidth, height: containerHeight } = entry.contentRect;
    setContainerSize(containerWidth, containerHeight);
    onResizeRef.current?.(containerWidth, containerHeight);
  };
  if (debounce > 0) {
    callback = throttle(callback, debounce, {
      trailing: true,
      leading: false,
    });
  }
  const observer = new ResizeObserver(callback);

  const { width: containerWidth, height: containerHeight } = containerRef.current.getBoundingClientRect();
  setContainerSize(containerWidth, containerHeight);

  observer.observe(containerRef.current);

  return () => {
    observer.disconnect();
  };
}, [setContainerSize, debounce]);

Container dimensions

Percentage dimensions

Use percentage values for fluid layouts:
<ResponsiveContainer width="100%" height="100%">
  <LineChart data={data}>
    <Line dataKey="value" stroke="#8884d8" />
  </LineChart>
</ResponsiveContainer>

Fixed dimensions

Use pixel values for fixed-size charts:
<ResponsiveContainer width={600} height={300}>
  <LineChart data={data}>
    <Line dataKey="value" stroke="#8884d8" />
  </LineChart>
</ResponsiveContainer>

Mixed dimensions

Combine percentage and fixed values:
<ResponsiveContainer width="100%" height={400}>
  <LineChart data={data}>
    <Line dataKey="value" stroke="#8884d8" />
  </LineChart>
</ResponsiveContainer>

Aspect ratio

Maintain a specific width-to-height ratio:
<ResponsiveContainer width="100%" aspect={16 / 9}>
  <LineChart data={data}>
    <Line dataKey="value" stroke="#8884d8" />
  </LineChart>
</ResponsiveContainer>
<ResponsiveContainer width="100%" aspect={16/9}>
  <LineChart data={data}>
    <Line dataKey="value" stroke="#8884d8" />
  </LineChart>
</ResponsiveContainer>
When using aspect, the height is calculated as width / aspect. This is useful for maintaining visual consistency across different screen sizes.

Minimum and maximum dimensions

Set constraints on chart size:
<ResponsiveContainer 
  width="100%" 
  height="100%"
  minWidth={300}
  minHeight={200}
  maxHeight={600}
>
  <LineChart data={data}>
    <Line dataKey="value" stroke="#8884d8" />
  </LineChart>
</ResponsiveContainer>

Debouncing resize events

Optimize performance during rapid resize events:
<ResponsiveContainer 
  width="100%" 
  height={400}
  debounce={200}  // Wait 200ms after resize before re-rendering
>
  <LineChart data={data}>
    <Line dataKey="value" stroke="#8884d8" />
  </LineChart>
</ResponsiveContainer>
Debouncing is useful when charts contain large datasets or complex rendering. It prevents excessive re-renders during window resizing.

Resize callback

Execute code when chart size changes:
import { useState } from 'react';
import { ResponsiveContainer, LineChart, Line } from 'recharts';

function ChartWithResizeTracking() {
  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
  
  return (
    <div>
      <p>Chart size: {dimensions.width}px × {dimensions.height}px</p>
      <ResponsiveContainer 
        width="100%" 
        height={400}
        onResize={(width, height) => {
          setDimensions({ width, height });
          console.log('Chart resized to:', width, height);
        }}
      >
        <LineChart data={data}>
          <Line dataKey="value" stroke="#8884d8" />
        </LineChart>
      </ResponsiveContainer>
    </div>
  );
}

Responsive patterns

Full-width charts

function FullWidthChart() {
  return (
    <div style={{ width: '100%', height: 400 }}>
      <ResponsiveContainer>
        <LineChart data={data}>
          <XAxis dataKey="name" />
          <YAxis />
          <Line dataKey="value" stroke="#8884d8" />
        </LineChart>
      </ResponsiveContainer>
    </div>
  );
}

Dashboard grid

function DashboardGrid() {
  return (
    <div style={{ 
      display: 'grid', 
      gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
      gap: 20,
    }}>
      <div style={{ height: 300 }}>
        <ResponsiveContainer>
          <LineChart data={data1}>
            <Line dataKey="value" stroke="#8884d8" />
          </LineChart>
        </ResponsiveContainer>
      </div>
      
      <div style={{ height: 300 }}>
        <ResponsiveContainer>
          <BarChart data={data2}>
            <Bar dataKey="value" fill="#82ca9d" />
          </BarChart>
        </ResponsiveContainer>
      </div>
      
      <div style={{ height: 300 }}>
        <ResponsiveContainer>
          <PieChart>
            <Pie data={data3} dataKey="value" />
          </PieChart>
        </ResponsiveContainer>
      </div>
    </div>
  );
}

Mobile-first design

import { useState, useEffect } from 'react';
import { ResponsiveContainer, LineChart, Line, XAxis, YAxis } from 'recharts';

function MobileFirstChart() {
  const [isMobile, setIsMobile] = useState(false);
  
  useEffect(() => {
    const checkMobile = () => setIsMobile(window.innerWidth < 768);
    checkMobile();
    window.addEventListener('resize', checkMobile);
    return () => window.removeEventListener('resize', checkMobile);
  }, []);
  
  return (
    <div style={{ width: '100%', height: isMobile ? 250 : 400 }}>
      <ResponsiveContainer>
        <LineChart 
          data={data}
          margin={isMobile 
            ? { top: 5, right: 5, left: 0, bottom: 5 }
            : { top: 20, right: 30, left: 20, bottom: 5 }
          }
        >
          <XAxis 
            dataKey="name" 
            tick={{ fontSize: isMobile ? 10 : 12 }}
            angle={isMobile ? -45 : 0}
            textAnchor={isMobile ? 'end' : 'middle'}
          />
          <YAxis tick={{ fontSize: isMobile ? 10 : 12 }} />
          <Line dataKey="value" stroke="#8884d8" strokeWidth={isMobile ? 1 : 2} />
        </LineChart>
      </ResponsiveContainer>
    </div>
  );
}

Breakpoint-based configuration

import { useState, useEffect } from 'react';
import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, Legend, Tooltip } from 'recharts';

function BreakpointChart() {
  const [breakpoint, setBreakpoint] = useState('large');
  
  useEffect(() => {
    const updateBreakpoint = () => {
      const width = window.innerWidth;
      if (width < 640) setBreakpoint('small');
      else if (width < 1024) setBreakpoint('medium');
      else setBreakpoint('large');
    };
    
    updateBreakpoint();
    window.addEventListener('resize', updateBreakpoint);
    return () => window.removeEventListener('resize', updateBreakpoint);
  }, []);
  
  const config = {
    small: {
      height: 200,
      layout: 'vertical',
      margin: { top: 5, right: 5, left: 40, bottom: 5 },
      showLegend: false,
    },
    medium: {
      height: 300,
      layout: 'horizontal',
      margin: { top: 20, right: 20, left: 20, bottom: 20 },
      showLegend: true,
    },
    large: {
      height: 400,
      layout: 'horizontal',
      margin: { top: 20, right: 30, left: 20, bottom: 5 },
      showLegend: true,
    },
  }[breakpoint];
  
  return (
    <div style={{ width: '100%', height: config.height }}>
      <ResponsiveContainer>
        <BarChart 
          data={data} 
          layout={config.layout}
          margin={config.margin}
        >
          {config.layout === 'horizontal' ? (
            <>
              <XAxis dataKey="name" />
              <YAxis />
            </>
          ) : (
            <>
              <XAxis type="number" />
              <YAxis dataKey="name" type="category" />
            </>
          )}
          <Tooltip />
          {config.showLegend && <Legend />}
          <Bar dataKey="value" fill="#8884d8" />
        </BarChart>
      </ResponsiveContainer>
    </div>
  );
}

Container queries (CSS)

Leverage modern CSS container queries with ResponsiveContainer:
// styles.css
.chart-container {
  container-type: size;
  width: 100%;
  height: 400px;
}

@container (max-width: 600px) {
  .chart-wrapper {
    height: 250px;
  }
}

@container (min-width: 601px) {
  .chart-wrapper {
    height: 400px;
  }
}

// Component
function ContainerQueryChart() {
  return (
    <div className="chart-container">
      <div className="chart-wrapper">
        <ResponsiveContainer>
          <LineChart data={data}>
            <Line dataKey="value" stroke="#8884d8" />
          </LineChart>
        </ResponsiveContainer>
      </div>
    </div>
  );
}

Performance considerations

Optimize large datasets

import { useMemo } from 'react';
import { ResponsiveContainer, LineChart, Line } from 'recharts';

function OptimizedChart({ rawData }) {
  // Downsample data on large screens, more aggressive on mobile
  const processedData = useMemo(() => {
    const isMobile = window.innerWidth < 768;
    const sampleRate = isMobile ? 10 : 5;
    return rawData.filter((_, index) => index % sampleRate === 0);
  }, [rawData]);
  
  return (
    <ResponsiveContainer width="100%" height={400}>
      <LineChart data={processedData}>
        <Line 
          dataKey="value" 
          stroke="#8884d8"
          isAnimationActive={false}  // Disable animation for better performance
          dot={false}  // Hide dots on mobile for performance
        />
      </LineChart>
    </ResponsiveContainer>
  );
}

Lazy loading charts

import { lazy, Suspense } from 'react';

const Chart = lazy(() => import('./Chart'));

function LazyChart() {
  return (
    <Suspense fallback={<div>Loading chart...</div>}>
      <Chart data={data} />
    </Suspense>
  );
}

Common issues

Ensure the parent container has explicit dimensions:
// Wrong - no height defined
<div>
  <ResponsiveContainer>
    <LineChart data={data} />
  </ResponsiveContainer>
</div>

// Correct - explicit height
<div style={{ height: 400 }}>
  <ResponsiveContainer>
    <LineChart data={data} />
  </ResponsiveContainer>
</div>
Add debounce to reduce re-renders:
<ResponsiveContainer debounce={100}>
  <LineChart data={data} />
</ResponsiveContainer>
Set minimum dimensions:
<ResponsiveContainer 
  width="100%" 
  height={400}
  minHeight={250}
>
  <LineChart data={data} />
</ResponsiveContainer>
Adjust chart margins based on legend position:
<LineChart 
  margin={{ top: 5, right: 20, bottom: 40, left: 20 }}
>
  <Legend verticalAlign="bottom" height={36} />
</LineChart>