Charts - Funnel
Use funnel charts to show how quantities change through sequential steps, such as conversion or engagement stages.
Overview
A funnel chart shows how a quantity narrows or grows through sequential steps. Use it for flows like audience engagement, education levels, or conversion pipelines.
The demo below shows a simple funnel with four decreasing values.
import Box from '@mui/material/Box';
import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
export default function BasicFunnel() {
return (
<Box sx={{ width: '100%', maxWidth: 400 }}>
<FunnelChart
series={[
{
data: [{ value: 200 }, { value: 180 }, { value: 90 }, { value: 50 }],
},
]}
height={300}
/>
</Box>
);
}
Basics
A funnel chart series must include a data property with an array of objects.
Each object is one section and must have a value property.
You can add optional properties such as label and id.
Legend
The funnel shows a legend by default.
Provide a label in each data object for the legend text.
Set hideLegend to true to hide the legend.
- A
- B
- C
- D
Pyramid chart
A pyramid chart is a funnel with an inverted profile.
Set the curve property to 'pyramid' on the series.
import Box from '@mui/material/Box';
import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
export default function PyramidFunnel() {
return (
<Box sx={{ width: '100%', maxWidth: 400 }}>
<FunnelChart
series={[
{
curve: 'pyramid',
data: [{ value: 10 }, { value: 90 }, { value: 180 }, { value: 400 }],
},
]}
height={300}
/>
</Box>
);
}
Labels
The funnel shows labels by default (each section's value).
Use the valueFormatter prop to format them.
import Box from '@mui/material/Box';
import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
export default function FunnelLabels() {
return (
<Box sx={{ width: '100%', maxWidth: 400 }}>
<FunnelChart
series={[
{
data: [
{ value: 200, label: 'A' },
{ value: 180, label: 'B' },
{ value: 90, label: 'C' },
{ value: 50, label: 'D' },
],
valueFormatter: (item, context) =>
`${item.label}${context.dataIndex} ${item.value}.00`,
},
]}
{...funnelProps}
/>
</Box>
);
}
const funnelProps = {
height: 300,
hideLegend: true,
} as const;
Styling labels
Use the funnelSectionClasses.label class to style labels.
import Box from '@mui/material/Box';
import { FunnelChart, funnelClasses } from '@mui/x-charts-pro/FunnelChart';
export default function FunnelLabelStyling() {
return (
<Box sx={{ width: '100%', maxWidth: 400 }}>
<FunnelChart
series={[
{
data: [{ value: 200 }, { value: 180 }, { value: 90 }, { value: 50 }],
},
]}
sx={{
[`& .${funnelClasses.sectionLabel}`]: {
fill: 'white',
textShadow: '1px 1px 2px rgba(0,0,0,0.5)',
},
}}
{...funnelProps}
/>
</Box>
);
}
const funnelProps = {
height: 300,
hideLegend: true,
} as const;
Positioning labels
The sectionLabel property controls label position.
It accepts an object with:
position.vertical:'top','middle', or'bottom'position.horizontal:'start','center', or'end'offset: space between the label and the section anchor. Pass a number for both axes, or{ x?, y? }.
textAnchor and dominantBaseline are forwarded to the SVG text element.
They behave like the SVG attributes of the same names, not like CSS properties, and the funnel chart only accepts the values below.
See text-anchor and dominant-baseline on MDN for what each keyword does.
textAnchor:'start','middle', or'end'dominantBaseline:'auto','baseline','hanging','middle','central','text-after-edge', or'text-before-edge'
Set sectionLabel to false to hide labels.
You can also pass a function that receives the data object and returns the label config.
- A
- B
- C
- D
import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
<FunnelChart
// Space to display the labels
series={[
{
sectionLabel: {
position: {
horizontal: 'start',
vertical: 'bottom'
},
textAnchor: 'start',
dominantBaseline: 'middle',
offset: {
x: -10,
y: 10
}
}
}
]}
/>Playground
import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
import ChartsUsageDemo from 'docs/src/modules/components/ChartsUsageDemo';
import Stack from '@mui/material/Stack';
export default function FunnelLabelPositioning() {
return (
// @focus-start @padding 2
<ChartsUsageDemo
componentName="Funnel label positioning"
data={
{
horizontal: {
knob: 'select',
defaultValue: 'start',
options: ['start', 'center', 'end'],
},
vertical: {
knob: 'select',
defaultValue: 'bottom',
options: ['top', 'middle', 'bottom'],
},
textAnchor: {
knob: 'select',
defaultValue: 'start',
options: ['start', 'middle', 'end'],
},
dominantBaseline: {
knob: 'select',
defaultValue: 'middle',
options: [
'auto',
'hanging',
'middle',
'central',
'text-after-edge',
'text-before-edge',
],
},
offsetX: {
knob: 'slider',
defaultValue: -10,
min: -50,
max: 50,
},
offsetY: {
knob: 'slider',
defaultValue: 10,
min: -50,
max: 50,
},
hide: {
knob: 'switch',
},
} as const
}
renderDemo={(props) => (
<Stack sx={{ width: '100%' }}>
<FunnelChart
series={[
{
layout: 'vertical',
data: [
{ value: 200, label: 'A' },
{ value: 180, label: 'B' },
{ value: 90, label: 'C' },
{ value: 50, label: 'D' },
],
sectionLabel: props.hide
? false
: {
position: {
horizontal: props.horizontal,
vertical: props.vertical,
},
textAnchor: props.textAnchor,
dominantBaseline: props.dominantBaseline,
offset: {
x: props.offsetX,
y: props.offsetY,
},
},
},
]}
height={300}
slotProps={{ legend: { direction: 'vertical' } }}
/>
</Stack>
)}
getCode={({ props }) => {
if (props.hide) {
return `import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
<FunnelChart
series={[
{
sectionLabel: false
}
]}
/>
`;
}
return `import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
<FunnelChart
// Space to display the labels
series={[
{
sectionLabel: {
position: {
horizontal: '${props.horizontal}',
vertical: '${props.vertical}'
},
textAnchor: '${props.textAnchor}',
dominantBaseline: '${props.dominantBaseline}',
offset: {
x: ${props.offsetX},
y: ${props.offsetY}
}
}
}
]}
/>
`;
}}
/>
);
}
Styling
Curve interpolation
Use the curve property to choose the shape between sections.
It accepts 'linear', 'linear-sharp', 'bump', 'pyramid', 'step', or 'step-pyramid'.
import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
<FunnelChart
series={[{
curve: 'bump',
variant: 'filled',
// borderRadius: 0,
}]}
gap={0}
/>Playground
import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
import ChartsUsageDemo from 'docs/src/modules/components/ChartsUsageDemo';
import Stack from '@mui/material/Stack';
import { populationByEducationLevelPercentageSeries } from './populationByEducationLevel';
const curveTypes = [
'bump',
'linear',
'linear-sharp',
'step',
'pyramid',
'step-pyramid',
] as const;
export default function FunnelCurves() {
return (
// @focus-start @padding 2
<ChartsUsageDemo
componentName="Funnel curve"
data={
{
curveType: {
knob: 'radio',
options: curveTypes,
defaultValue: curveTypes[0],
},
gap: {
knob: 'slider',
defaultValue: 0,
min: 0,
max: 20,
},
borderRadius: {
knob: 'slider',
defaultValue: 0,
min: 0,
max: 20,
},
variant: {
knob: 'select',
options: ['filled', 'outlined'],
defaultValue: 'filled',
},
} as const
}
renderDemo={(props) => (
<Stack sx={{ width: '100%' }}>
<FunnelChart
series={[
{
curve: props.curveType,
borderRadius: props.borderRadius,
layout: 'vertical',
variant: props.variant,
funnelDirection: 'increasing',
...populationByEducationLevelPercentageSeries,
},
]}
gap={props.gap}
height={300}
slotProps={{ legend: { direction: 'vertical' } }}
/>
<FunnelChart
series={[
{
curve: props.curveType,
borderRadius: props.borderRadius,
layout: 'horizontal',
variant: props.variant,
funnelDirection: 'increasing',
...populationByEducationLevelPercentageSeries,
},
]}
gap={props.gap}
height={300}
slotProps={{ legend: { direction: 'vertical' } }}
/>
</Stack>
)}
getCode={({ props }) => {
return `import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
<FunnelChart
series={[{
curve: '${props.curveType}',
variant: '${props.variant}',
${props.curveType === 'bump' ? '// ' : ''}borderRadius: ${props.borderRadius},
}]}
gap={${props.gap}}
/>
`;
}}
/>
);
}
Gap
Use the gap property to set the space between sections (in pixels).
import Box from '@mui/material/Box';
import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
export default function FunnelGap() {
return (
<Box sx={{ width: '100%', maxWidth: 400 }}>
<FunnelChart
series={[
{
data: [{ value: 200 }, { value: 180 }, { value: 90 }, { value: 50 }],
},
]}
height={300}
gap={10}
/>
</Box>
);
}
Border radius
Use the borderRadius property to round section corners (in pixels).
The bump curve ignores border radius.
The linear, linear-sharp, and pyramid curves respect it partly, depending on section angles.
The step and step-pyramid curves respect it fully.
See Curve interpolation for how curve and borderRadius interact.
If gap is 0, radius applies only to corners not connected to another section.
If gap is greater than 0, radius applies to all corners.
Variant
Use the variant property to switch between styles:
'filled'(default): solid fill, no stroke'outlined': translucent fill with a colored stroke
The outlined variant is lighter visually.
- Leads
- Calls
- Meetings
- Deals
Colors
You can customize funnel colors in two ways:
- Pass a color palette. Each section uses a color from the palette.
- Set a
colorproperty on each data object to override the palette for that section.
CSS
You can style the funnel with CSS.
Each section group has a data-series attribute for targeting.
Use :nth-child or :nth-of-type to target specific sections, as in the demo below.
import Box from '@mui/material/Box';
import { FunnelChart, funnelClasses } from '@mui/x-charts-pro/FunnelChart';
export default function FunnelDataAttributes() {
return (
<Box sx={{ width: '100%', maxWidth: 400 }}>
<FunnelChart
{...funnelProps}
sx={{
[`[data-series="main"] .${funnelClasses.section}:nth-of-type(1)`]: {
fill: 'url(#pattern)',
},
}}
>
<defs>
<pattern id="pattern" width="50" height="50" patternUnits="userSpaceOnUse">
<rect width="100%" height="100%" fill="hotpink" />
<circle fill="slateblue" cx="15" cy="15" r="10" />
<circle fill="slateblue" cx="40" cy="40" r="10" />
</pattern>
</defs>
</FunnelChart>
</Box>
);
}
const funnelProps = {
height: 300,
hideLegend: true,
series: [
{
id: 'main',
data: [{ value: 200 }, { value: 180 }, { value: 90 }, { value: 50 }],
},
],
} as const;
Multiple funnels
By default, multiple series are stacked. Pass multiple series and use different colors or styles to tell them apart. The first series is at the bottom, the last at the top.
- A1
- B1
- C1
- D1
- A2
- B2
- C2
- D2
import Box from '@mui/material/Box';
import type { FunnelChartProps } from '@mui/x-charts-pro/FunnelChart';
import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
export default function FunnelStacked() {
return (
<Box sx={{ width: '100%', maxWidth: 500 }}>
<FunnelChart
sx={{ '& [data-series="big"]': { filter: 'brightness(0.7)' } }}
series={[
{
id: 'big',
data: dataBig,
sectionLabel: {
position: { horizontal: 'end' },
textAnchor: 'start',
offset: { x: 10 },
},
},
{ data: dataSmall, curve: 'bump' },
]}
height={300}
/>
</Box>
);
}
const dataBig: FunnelChartProps['series'][any]['data'] = [
{ value: 500, label: 'A1' },
{ value: 280, label: 'B1' },
{ value: 190, label: 'C1' },
{ value: 70, label: 'D1' },
];
const dataSmall: FunnelChartProps['series'][any]['data'] = [
{ value: 200, label: 'A2' },
{ value: 180, label: 'B2' },
{ value: 90, label: 'C2' },
{ value: 50, label: 'D2' },
];
Highlight
Set highlightScope.highlight to 'item' to highlight the hovered section.
Set highlightScope.fade to 'global' to fade the other sections.
Category axis
The funnel uses a category axis that follows the chart orientation. By default, the axis is hidden.
To show it, pass position and categories to the categoryAxis prop.
import Box from '@mui/material/Box';
import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
import { populationByEducationLevelPercentageSeriesLabeled } from './populationByEducationLevel';
export default function FunnelCategoryAxis() {
return (
<Box sx={{ width: '100%', maxWidth: 400 }}>
<FunnelChart
series={[populationByEducationLevelPercentageSeriesLabeled]}
categoryAxis={{
categories: ['First', 'Second', 'Third', 'Fourth', 'Fifth'],
position: 'left',
disableLine: true,
disableTicks: true,
size: 60,
}}
{...funnelProps}
/>
</Box>
);
}
const funnelProps = {
height: 300,
hideLegend: true,
} as const;
Scaled sections
By default, sections use the band scale (equal width).
Set scaleType to 'linear' in the categoryAxis configuration to scale section width by value.
import Box from '@mui/material/Box';
import { FunnelChart } from '@mui/x-charts-pro/FunnelChart';
import { populationByEducationLevelPercentageSeriesLabeled } from './populationByEducationLevel';
export default function FunnelLinearScale() {
return (
<Box sx={{ width: '100%', maxWidth: 400 }}>
<FunnelChart
series={[populationByEducationLevelPercentageSeriesLabeled]}
categoryAxis={{ scaleType: 'linear' }}
{...funnelProps}
/>
</Box>
);
}
const funnelProps = {
height: 300,
hideLegend: true,
} as const;
Auto-sizing axis
You can set the axis size to 'auto' to automatically calculate the axis dimension based on tick label measurements.
This is useful when your tick labels have varying lengths.
API
See the documentation below for a complete reference to all of the props and classes available to the components mentioned here.