Themes & Styling
Themes
Victory themes are reusable style configurations that enable you to standardize the appearance of charts across your application. Themes simplify chart development by reducing repetitive styling logic and ensuring visual consistency.
Themes are applied at the chart level and automatically cascade to all child components, such as axes, bars, lines, and legends. Victory provides built-in themes like clean
, material
and grayscale
, but you can also create custom themes to match your branding.
How Themes Work in Victory
Victory themes are essentially JavaScript objects that define styling properties for various chart elements. These theme configurations enable consistent and reusable styling across charts. Each theme configuration variable corresponds to a specific chart element and takes props that define its styles.
Theme configuration variables include:
.palette
- Defines color schemes used across the theme.
.chart
- Global styles like background and padding.
.area
.axis
.polarAxis
.polarDependentAxis
.bar
.boxplot
.candlestick
.errorbar
.group
.histogram
.legend
.line
.pie
.scatter
.stack
.tooltip
.voronoi
Each configuration variable takes props specific to its chart element, allowing customization of styles like colors, padding, labels, and more. For detailed information about each variable, refer to the VictoryTheme API page.
When a theme is passed to a chart via the theme
prop, the styles from the theme object are applied to the corresponding child components unless they are explicitly overridden by inline props.
<VictoryChart theme={VictoryTheme.material} > <VictoryBar /> </VictoryChart>
Predefined Themes
Victory includes several built-in themes to help you quickly style your charts:
Theme | Description |
---|---|
VictoryTheme.clean | A minimalist theme with no gridlines or extra styling, perfect for clean and modern visualizations. |
VictoryTheme.material | Inspired by Google's Material Design, this theme includes bold colors and a structured grid. |
VictoryTheme.grayscale | A neutral theme featuring grayscale tones, ideal for muted and professional-looking charts. |
Each of these themes can be applied to your Victory components by passing it into the theme
prop.
const result = [...Array(10).keys()]; const scatterData = [ ...Array(20).keys(), ].forEach((i) => ({ x: (i - 10) / 3, y: i / 2 - 2 * Math.random() - 4, })); const toInteger = (number) => parseInt(number).toString(); const DemoComponent = () => { const [theme, setTheme] = React.useState( VictoryTheme.grayscale, ); const positions = [ { transform: "translate(0, -15)" }, { transform: "translate(180, -40)", }, { transform: "translate(-10, 140)", }, { transform: "translate(180, 140)", }, ]; return ( <div> <div className="mb-8 p-4 mx-auto flex justify-between w-full"> <button className="bg-blue-600 border-none rounded-md text-white uppercase py-3 px-6 hover:bg-blue-700 cursor-pointer" onClick={() => setTheme(VictoryTheme.clean) } > clean </button> <button className="bg-orange-600 border-none rounded-md text-white uppercase py-3 px-6 hover:bg-orange-700 cursor-pointer" onClick={() => setTheme( VictoryTheme.material, ) } > material </button> <button className="bg-gray-600 border-none rounded-md text-white uppercase py-3 px-6 hover:bg-gray-700 cursor-pointer" onClick={() => setTheme( VictoryTheme.grayscale, ) } > grayscale </button> </div> <svg viewBox="0 0 400 400" role="img" aria-labelledby="title desc" style={{ height: "auto", width: "100%", }} > <g transform={ positions[0].transform } > <VictoryPie theme={theme} standalone={false} style={{ labels: { padding: 10 }, }} height={200} width={200} /> </g> <g transform={ positions[1].transform } > <VictoryChart theme={theme} standalone={false} height={250} width={250} > <VictoryAxis tickCount={3} tickFormat={toInteger} /> <VictoryAxis tickCount={4} dependentAxis /> <VictoryScatter size={2} data={scatterData} /> </VictoryChart> </g> <g transform={ positions[2].transform } > <VictoryChart theme={theme} standalone={false} height={250} width={250} > <VictoryAxis tickCount={4} domain={[0, 3]} tickFormat={toInteger} /> <VictoryAxis tickCount={4} dependentAxis domain={[0, 10]} /> <VictoryLine y={(data) => data.x * data.x } /> </VictoryChart> </g> <g transform={ positions[3].transform } > <VictoryChart standalone={false} theme={theme} height={250} width={250} domainPadding={{ x: 40 }} > <VictoryAxis tickFormat={[ "A", "B", "C", ]} /> <VictoryAxis tickCount={3} dependentAxis /> <VictoryStack> <VictoryBar data={[ { x: "A", y: 1, }, { x: "B", y: 3, }, { x: "C", y: 3, }, ]} /> <VictoryBar data={[ { x: "A", y: 2, }, { x: "B", y: 1, }, { x: "C", y: 3, }, ]} /> <VictoryBar data={[ { x: "A", y: 3, }, { x: "B", y: 1, }, { x: "C", y: 1, }, ]} /> </VictoryStack> </VictoryChart> </g> </svg> </div> ); }; render(<DemoComponent />);
You can also customize these themes or use them as a base to create your own. To build upon a predefined theme, you can extend it using the spread operator:
const extendedTheme = {
...VictoryTheme.material,
axis: {
...VictoryTheme.material.axis,
style: {
...VictoryTheme.material.axis
.style,
tickLabels: {
fill: "#444",
fontSize: 10,
fontStyle: "italic",
},
},
},
};
Creating a Custom Theme
To create a completely custom theme, define a JavaScript object that includes styles for the components you want to theme. You can omit components that use default styling.
const customTheme = { axis: { style: { grid: { stroke: "none" }, axis: { stroke: "#333", strokeWidth: 2, }, ticks: { stroke: "#555", size: 5, }, tickLabels: { fill: "#222", fontSize: 12, padding: 5, }, }, }, bar: { style: { data: { fill: "#0074d9", width: 15, }, }, }, }; render( <VictoryChart theme={customTheme} domainPadding={{ x: 40 }} > <VictoryBar data={[ { x: 1, y: 2 }, { x: 2, y: 4 }, { x: 3, y: 6 }, ]} /> </VictoryChart>, );
To enhance the "Styles" section of the Victory Themes guide, consider incorporating the following detailed explanations and examples:
Styling Individual Components
To customize the appearance of Victory components, you can use the style
prop, which accepts an object containing styles for various component elements like data
, labels
, and parent
. For a detailed breakdown of the style options available, refer to the Victory Style Interface.
Example: Customizing Bar and Line Colors
<VictoryChart theme={VictoryTheme.clean} domain={{ x: [0, 4] }} > <VictoryBar style={{ data: { fill: "red" } }} data={[ { x: 1, y: 2 }, { x: 2, y: 4 }, { x: 3, y: 6 }, ]} /> <VictoryLine style={{ data: { stroke: "blue", strokeWidth: 5, }, }} y={(d) => d.x} /> </VictoryChart>
Styling Data
To style individual elements within a dataset, you can include style attributes directly in your data objects and utilize functional styles.
Note: Continuous data components like VictoryLine
and VictoryArea
render a single SVG element for the entire dataset, so individual styling of data points within these components is not applicable.
<VictoryChart> <VictoryBar style={{ data: { fill: ({ datum }) => datum.fill, }, }} data={[ { x: 1, y: 2, fill: "red" }, { x: 2, y: 4, fill: "orange" }, { x: 3, y: 6, fill: "gold" }, ]} /> <VictoryScatter style={{ data: { fill: ({ index }) => index % 2 === 0 ? "blue" : "grey", stroke: ({ datum }) => datum.y < 6 ? "red" : "black", strokeWidth: 2, }, }} symbol={({ datum }) => datum.x > 1 ? "plus" : "square" } size={({ datum }) => datum.y + 2} data={[ { x: 0, y: 2 }, { x: 1, y: 4 }, { x: 2, y: 6 }, { x: 3, y: 8 }, { x: 4, y: 10 }, ]} /> </VictoryChart>
Using Gradient Fills
To apply gradient fills to your charts, define a gradient in the SVG defs
section and reference it by id in your component's style. Gradients can be used to give continuous charts (i.e. line or area charts) the appearance of discrete data elements and hover states.
<div> <svg style={{ height: 0 }}> <defs> <linearGradient id="myGradient"> <stop offset="0%" stopColor="red" /> <stop offset="25%" stopColor="orange" /> <stop offset="50%" stopColor="gold" /> <stop offset="75%" stopColor="yellow" /> <stop offset="100%" stopColor="green" /> </linearGradient> </defs> </svg> <VictoryChart theme={VictoryTheme.clean} > <VictoryArea style={{ data: { fill: "url(#myGradient)", }, }} data={[ { x: 1, y: 2 }, { x: 2, y: 3 }, { x: 3, y: 7 }, { x: 4, y: 4 }, { x: 5, y: 5 }, ]} /> </VictoryChart> </div>