Bar
Bar charts renders a dataset as series of bars and is used for comparing numeric values between different categories.
Basic
See the full API here. Typically composed with VictoryChart to create full charts.
<VictoryChart domainPadding={{ x: 20 }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} /> </VictoryChart>
Bar Charts - Domain
Bars in VictoryBar are centered around their corresponding value by default. You can move your bars away from your axis by setting a new domain, adding domainPadding, or changing how bars are aligned relative to their values with the alignment prop on VictoryBar.
Using domainPadding to adjust the bar position is the most common way to adjust the position of bars in a chart.
<VictoryChart domainPadding={{ x: 50 }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} /> </VictoryChart>
Setting the bar alignment using the alignment prop.
<VictoryChart theme={VictoryTheme.clean} > <VictoryBar alignment="start" data={sampleData} /> </VictoryChart>
Setting the bar alignment using the domain prop.
<VictoryChart domain={{ x: [0.5, 5.5] }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} /> </VictoryChart>
Bar Charts - Horizontal
Bar charts can be rendered horizontally by setting the horizontal prop to true. This prop can be applied to either VictoryChart or VictoryBar.
<VictoryChart domainPadding={{ x: 20 }} horizontal theme={VictoryTheme.clean} > <VictoryBar /> </VictoryChart>
Bar Charts - Labels
Add labels to charts by setting the labels prop to the name of a property in the dataset, or a function that returns the label value. You can customize the display of the labels by using the labelComponent prop.
<VictoryChart domainPadding={{ x: 20 }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} labels={({ datum }) => datum.y} /> </VictoryChart>
Bar Charts - Tooltips
Tooltips can be added by using a VictoryTooltip component as the labelComponent.
<VictoryChart domainPadding={{ x: 20 }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} labelComponent={<VictoryTooltip />} labels={({ datum }) => datum.y} /> </VictoryChart>
Bar Charts - Grouped
Bar charts can be grouped to show how different subcategories compare to each other.
function App() { return ( <VictoryChart theme={VictoryTheme.clean} domain={{ y: [0.5, 5.5] }} domainPadding={{ x: 40 }} > <VictoryGroup offset={20} style={{ data: { width: 15 } }} > <VictoryBar data={[ { x: "2023 Q1", y: 1 }, { x: "2023 Q2", y: 2 }, { x: "2023 Q3", y: 3 }, { x: "2023 Q4", y: 2 }, ]} /> <VictoryBar data={[ { x: "2023 Q1", y: 2 }, { x: "2023 Q2", y: 3 }, { x: "2023 Q3", y: 4 }, { x: "2023 Q4", y: 5 }, ]} /> <VictoryBar data={[ { x: "2023 Q1", y: 1 }, { x: "2023 Q2", y: 2 }, { x: "2023 Q3", y: 3 }, { x: "2023 Q4", y: 4 }, ]} /> </VictoryGroup> </VictoryChart> ); } render(<App />);
Bar Charts - Grouped Labels
Bar chart labels for grouped bars can be rendered by setting the labels prop to the name of a property in the dataset, an array, or a function that returns the label value.
function App() { return ( <VictoryChart theme={VictoryTheme.clean} domain={{ y: [0.5, 5.5] }} domainPadding={{ x: 40 }} > <VictoryGroup offset={20} style={{ data: { width: 15 } }} > <VictoryBar data={[ { x: "2023 Q1", y: 1 }, { x: "2023 Q2", y: 2 }, { x: "2023 Q3", y: 3 }, { x: "2023 Q4", y: 2 }, ]} labels={({ datum }) => datum.y } /> <VictoryBar data={[ { x: "2023 Q1", y: 2 }, { x: "2023 Q2", y: 3 }, { x: "2023 Q3", y: 4 }, { x: "2023 Q4", y: 5 }, ]} labels={({ datum }) => datum.y } /> <VictoryBar data={[ { x: "2023 Q1", y: 1 }, { x: "2023 Q2", y: 2 }, { x: "2023 Q3", y: 3 }, { x: "2023 Q4", y: 4 }, ]} labels={({ datum }) => datum.y } /> </VictoryGroup> </VictoryChart> ); } render(<App />);
Bar Charts - Combination
Bar charts can be rendered with other chart types like Line.
<VictoryChart domainPadding={{ x: 20 }} horizontal theme={VictoryTheme.clean} > <VictoryBar /> <VictoryLine /> </VictoryChart>
Bar Charts - Animation
Charts can be animated by setting the animate prop. See the animations guide for more information.
function App() { const [data, setData] = React.useState(getData()); React.useState(() => { const setStateInterval = window.setInterval(() => { setData(getData()); }, 4000); return () => { window.clearInterval( setStateInterval, ); }; }, []); return ( <VictoryChart theme={VictoryTheme.clean} domainPadding={{ x: 20 }} > <VictoryBar animate={{ duration: 1000 }} data={data} /> </VictoryChart> ); } function getData() { return [ { x: 1, y: _.random(1, 5) }, { x: 2, y: _.random(1, 10) }, { x: 3, y: _.random(2, 10) }, { x: 4, y: _.random(2, 10) }, { x: 5, y: _.random(2, 15) }, { x: 6, y: _.random(2, 8) }, { x: 7, y: _.random(2, 11) }, ]; } render(<App />);
Bar Charts - Zoom & Pan
Bar charts support pan and zoom behavior by using the VictoryZoomContainer component. See the Pan & Zoom guide for more information.
<VictoryChart domain={{ x: [0, 10] }} theme={VictoryTheme.clean} containerComponent={ <VictoryZoomContainer zoomDimension="x" zoomDomain={{ x: [0, 5] }} minimumZoom={{ x: 1 }} /> } > <VictoryBar data={[ { x: 1, y: 2 }, { x: 2, y: 3 }, { x: 3, y: 5 }, { x: 4, y: 4 }, { x: 5, y: 7 }, { x: 6, y: 6 }, { x: 7, y: 8 }, { x: 8, y: 9 }, { x: 9, y: 10 }, { x: 10, y: 12 }, ]} /> </VictoryChart>
Bar Charts - Styles
Chart styling can be customized by using the theme or overriding the style prop on the component.
<VictoryChart domainPadding={{ x: 20 }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} labels={({ datum }) => datum.y} style={{ data: { fill: "#c43a31", fillOpacity: 0.4, stroke: "#c43a31", strokeWidth: 2, }, labels: { fontSize: 12, fill: "#c43a31", }, }} /> </VictoryChart>
Bar Charts - Events
Events can be handled by passing an array of event objects to the events prop on the component. Each event object should specify a target and an eventHandlers object. See the events guide for more information.
function App() { const toggleFillColor = (fill) => { if (fill === "black") { return null; } else { return { style: { fill: "black", }, }; } }; return ( <VictoryChart domainPadding={{ x: 20 }} theme={VictoryTheme.clean} > <VictoryBar data={sampleData} labels={({ datum }) => datum.y} events={[ { target: "data", eventHandlers: { onClick: () => { return [ { target: "data", mutation: (props) => toggleFillColor( props.style ?.fill, ), }, ]; }, }, }, ]} /> </VictoryChart> ); } render(<App />);
Stacked Bar Charts
Bar charts can be stacked to show how different categories contribute to the total.
<VictoryChart domainPadding={{ x: 40 }} theme={VictoryTheme.clean} > <VictoryStack> <VictoryBar data={[ { x: "Sales", y: 2 }, { x: "Marketing", y: 3 }, { x: "Finance", y: 5 }, ]} /> <VictoryBar data={[ { x: "Sales", y: 1 }, { x: "Marketing", y: 4 }, { x: "Finance", y: 5 }, ]} /> <VictoryBar data={[ { x: "Sales", y: 3 }, { x: "Marketing", y: 2 }, { x: "Finance", y: 6 }, ]} /> </VictoryStack> </VictoryChart>
Stacked Bar Charts - 100%
While Victory does not support 100% stacked bar charts natively, you can achieve this by transforming your data.
const myDataset = [ [ { x: "a", y: 1 }, { x: "b", y: 2 }, { x: "c", y: 3 }, { x: "d", y: 2 }, { x: "e", y: 3 }, ], [ { x: "a", y: 2 }, { x: "b", y: 3 }, { x: "c", y: 7 }, { x: "d", y: 5 }, { x: "e", y: 3 }, ], [ { x: "a", y: 5 }, { x: "b", y: 2 }, { x: "c", y: 3 }, { x: "d", y: 4 }, { x: "e", y: 4 }, ], ]; function App() { // This is an example of a function you might // use to transform your data to make 100% data function transformData(dataset) { const totals = dataset[0].map( (data, i) => { return dataset.reduce( (memo, curr) => { return memo + curr[i].y; }, 0, ); }, ); return dataset.map((data) => { return data.map((datum, i) => { return { x: datum.x, y: (datum.y / totals[i]) * 100, }; }); }); } const dataset = transformData(myDataset); return ( <div> <VictoryChart domainPadding={{ x: 30, y: 20 }} theme={VictoryTheme.clean} > <VictoryStack> {dataset.map((data, i) => { return ( <VictoryBar data={data} key={i} /> ); })} </VictoryStack> <VictoryAxis dependentAxis tickFormat={(tick) => `${tick}%` } /> <VictoryAxis tickFormat={[ "a", "b", "c", "d", "e", ]} /> </VictoryChart> </div> ); } render(<App />);
Stacked Bar Charts - Grouped
Bar charts can be stacked and grouped to show how different subcategories contribute to the total.
function App() { const getBarData = () => { return [1, 2, 3, 4, 5].map(() => { return [ { x: 1, y: Math.random() }, { x: 2, y: Math.random() }, { x: 3, y: Math.random() }, ]; }); }; return ( <div> <VictoryChart domainPadding={{ x: 50 }} > <VictoryGroup offset={20} style={{ data: { width: 15 }, }} > <VictoryStack colorScale={"red"} > {getBarData().map( (data, index) => { return ( <VictoryBar key={index} data={data} /> ); }, )} </VictoryStack> <VictoryStack colorScale={"green"} > {getBarData().map( (data, index) => { return ( <VictoryBar key={index} data={data} /> ); }, )} </VictoryStack> <VictoryStack colorScale={"blue"} > {getBarData().map( (data, index) => { return ( <VictoryBar key={index} data={data} /> ); }, )} </VictoryStack> </VictoryGroup> </VictoryChart> </div> ); } render(<App />);
Diverging Bar Charts
Diverging bar are useful for showing how different categories compare to a common baseline. By default, Victory will calculate the domain based on the data provided.
<VictoryChart domainPadding={{ x: 50 }} theme={VictoryTheme.clean} > <VictoryBar data={[ { x: "rabbits", y: 5 }, { x: "cats", y: -10 }, { x: "dogs", y: 15 }, { x: "turtles", y: -8 }, { x: "snakes", y: -2 }, { x: "fish", y: 5 }, ]} /> </VictoryChart>
Diverging Bar Charts - Horizontal
Diverging bar are useful for showing how different categories compare to a common baseline. By default, Victory will calculate the domain based on the data provided.
<VictoryChart horizontal domainPadding={{ x: 50 }} theme={VictoryTheme.clean} > <VictoryBar data={[ { x: "rabbits", y: 5 }, { x: "cats", y: -10 }, { x: "dogs", y: 15 }, { x: "turtles", y: -8 }, { x: "snakes", y: -2 }, { x: "fish", y: 5 }, ]} /> </VictoryChart>
Diverging Bar Charts - Grouped
Diverging bar are useful for showing how different categories compare to a common baseline. By default, Victory will calculate the baseline based on the data provided.
function App() { return ( <VictoryChart domainPadding={{ x: 50 }} theme={VictoryTheme.clean} > <VictoryGroup offset={18} colorScale={"qualitative"} > {getBarData().map( (data, index) => { return ( <VictoryBar key={index} data={data} labels={({ datum }) => datum.y } /> ); }, )} </VictoryGroup> </VictoryChart> ); } function getBarData() { return _.range(5).map(() => { return [ { x: "rabbits", y: _.random(-5, 5), }, { x: "cats", y: _.random(-10, 10), }, { x: "dogs", y: _.random(-15, 15), }, ]; }); } render(<App />);
Diverging Bar Charts - Floating
Diverging bar are useful for showing how different categories compare to a common baseline.
const dataA = [ { x: "Television", y: 38 }, { x: "Smartwatch", y: 37 }, { x: "Fitness Monitor", y: 25 }, { x: "Tablet", y: 19 }, { x: "Camera", y: 15 }, { x: "Laptop", y: 13 }, { x: "Phone", y: 12 }, ]; const dataB = dataA.map((point) => { const y = Math.round( point.y + 3 * (Math.random() - 0.75), ); return { ...point, y }; }); const width = 400; const height = 300; function App() { return ( <VictoryChart horizontal height={height} width={width} padding={{ top: 100, bottom: 30, left: 50, right: 50, }} theme={VictoryTheme.clean} > <VictoryLegend x={90} y={20} orientation="horizontal" gutter={20} data={[ { name: "Ages 18-20", }, { name: "Ages 21-24", }, ]} /> <VictoryStack style={{ data: { width: 12 }, labels: { fontSize: 12 }, }} > <VictoryBar data={dataA} y={(data) => -Math.abs(data.y) } labels={({ datum }) => `${Math.abs(datum.y)}%` } /> <VictoryBar data={dataB} labels={({ datum }) => `${Math.abs(datum.y)}%` } /> </VictoryStack> <VictoryAxis style={{ axis: { stroke: "transparent", }, ticks: { stroke: "transparent", }, tickLabels: { fontSize: 12, fill: "black", }, }} /* Use a custom tickLabelComponent with an absolutely positioned x value to position your tick labels in the center of the chart. The correct y values are still provided by VictoryAxis for each tick */ tickLabelComponent={ <VictoryLabel x={width / 2} textAnchor="middle" /> } tickValues={dataA .map((point) => point.x) .reverse()} /> </VictoryChart> ); } render(<App />);
Polar Bar Charts
Bar charts can be rendered in polar coordinates by setting the polar prop to true and using VictoryPolarAxis components.
<VictoryChart polar theme={VictoryTheme.clean} > <VictoryPolarAxis dependentAxis style={{ axis: { stroke: "none" } }} tickFormat={() => null} /> <VictoryPolarAxis /> <VictoryBar data={sampleData} /> </VictoryChart>
Polar Bar Charts - Stacked
Bar charts can be rendered in polar coordinates by setting the polar prop to true and using VictoryPolarAxis components.
const directions = { 0: "E", 45: "NE", 90: "N", 135: "NW", 180: "W", 225: "SW", 270: "S", 315: "SE", }; const orange = { base: "#2D7FF9", highlight: "#2750AE", }; const red = { base: "#8B46FF", highlight: "#6B1CB0", }; const innerRadius = 30; function CompassCenter(props) { const { origin } = props; const circleStyle = { stroke: red.base, strokeWidth: 2, fill: orange.base, }; return ( <g> <circle cx={origin.x} cy={origin.y} r={innerRadius} style={circleStyle} /> </g> ); } function CenterLabel(props) { const { datum, active, color } = props; const text = [ `${directions[datum._x]}`, `${Math.round(datum._y1)} mph`, ]; const baseStyle = { fill: color.highlight, textAnchor: "middle", }; const style = [ { ...baseStyle, fontSize: 18, fontWeight: "bold", }, { ...baseStyle, fontSize: 12 }, ]; return active ? ( <VictoryLabel text={text} style={style} x={75} y={75} renderInPortal /> ) : null; } function App() { const [state, setState] = React.useState({ wind: getWindData(), }); return ( <VictoryChart polar animate={{ duration: 500, onLoad: { duration: 500 }, }} theme={VictoryTheme.clean} innerRadius={innerRadius} domainPadding={{ y: 10 }} events={[ { childName: "all", target: "data", eventHandlers: { onMouseOver: () => { return [ { target: "labels", mutation: () => ({ active: true, }), }, { target: "data", mutation: () => ({ active: true, }), }, ]; }, onMouseOut: () => { return [ { target: "labels", mutation: () => ({ active: false, }), }, { target: "data", mutation: () => ({ active: false, }), }, ]; }, }, }, ]} > <VictoryPolarAxis dependentAxis labelPlacement="vertical" style={{ axis: { stroke: "none" }, }} tickFormat={() => ""} /> <VictoryPolarAxis labelPlacement="parallel" tickValues={_.keys( directions, ).map((k) => +k)} tickFormat={_.values( directions, )} /> <VictoryStack> <VictoryBar style={{ data: { fill: ({ active }) => active ? orange.highlight : orange.base, width: 40, }, }} data={state.wind} x="windBearing" y="windSpeed" labels={() => ""} labelComponent={ <CenterLabel color={orange} /> } /> <VictoryBar style={{ data: { fill: (d, a) => a ? red.highlight : red.base, width: 40, }, }} data={state.wind} x="windBearing" y={(d) => d.windGust - d.windSpeed } labels={() => ""} labelComponent={ <CenterLabel color={red} /> } /> </VictoryStack> <CompassCenter /> </VictoryChart> ); } function getWindData() { return _.keys(directions).map((d) => { const speed = Math.floor(_.random() * 17) + 4; return { windSpeed: speed, windGust: speed + _.random(2, 10), windBearing: +d, }; }); } render(<App />);
Standalone Rendering
Bar charts can be rendered outside a VictoryChart.
<VictoryBar theme={VictoryTheme.clean} />
They can also be embeded in other SVG components by using the standalone prop.
<div style={{ padding: "20px" }}> <svg width={300} height={300} style={{ display: "block", margin: "0 auto", }} > <circle cx={150} cy={150} r={150} fill="#9ded91" /> <VictoryBar standalone={false} theme={VictoryTheme.clean} width={300} height={300} padding={{ left: 10, right: 10 }} data={sampleData} /> </svg> </div>