Chart.js Chart Styling and Customization
Chart.js provides rich styling customization options, allowing developers to create charts that match brand styles and design requirements. This chapter will detail how to customize style and appearance of Chart.js charts.
Global Style Configuration
1. Global Default Configuration
You can set global default styles by modifying Chart.defaults:
javascript
// Set global default configuration
Chart.defaults.borderColor = '#ccc';
Chart.defaults.color = '#666';
Chart.defaults.font.family = 'Arial, sans-serif';
Chart.defaults.font.size = 14;
Chart.defaults.font.weight = 'normal';
Chart.defaults.responsive = true;
Chart.defaults.maintainAspectRatio = false;
// Charts will use these global default values when created
const myChart = new Chart(ctx, {
type: 'bar',
data: {
// ... data configuration
}
// Unspecified configurations in options will use global defaults
});2. Chart-level Configuration
When creating a chart, you can configure styles through options parameter:
javascript
const myChart = new Chart(ctx, {
type: 'bar',
data: {
// ... data configuration
},
options: {
// Chart-level style configuration
responsive: true,
maintainAspectRatio: false,
backgroundColor: '#f8f9fa',
borderColor: '#dee2e6',
borderWidth: 1,
// Font configuration
font: {
family: 'Arial, sans-serif',
size: 14,
weight: 'normal',
lineHeight: 1.2
},
// Layout configuration
layout: {
padding: {
top: 20,
right: 20,
bottom: 20,
left: 20
}
}
}
});Color Customization
1. Dataset Colors
You can set different colors for each dataset:
javascript
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June'],
datasets: [{
label: 'Sales',
data: [12, 19, 3, 5, 2, 3],
// Background colors
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 205, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
// Border colors
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 205, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
// Border width
borderWidth: 2
}]
}
});2. Gradient Colors
You can use Canvas gradient function to create gradient color effects:
javascript
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June'],
datasets: [{
label: 'Sales',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: function(context) {
const chart = context.chart;
const {ctx, chartArea} = chart;
if (!chartArea) {
// If chart area is undefined, return default color
return 'rgba(54, 162, 235, 0.2)';
}
// Create linear gradient
const gradient = ctx.createLinearGradient(0, chartArea.top, 0, chartArea.bottom);
gradient.addColorStop(0, 'rgba(54, 162, 235, 0.8)');
gradient.addColorStop(1, 'rgba(54, 162, 235, 0.2)');
return gradient;
},
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 2
}]
}
});Font and Text Styles
1. Title Styles
javascript
const myChart = new Chart(ctx, {
type: 'bar',
data: {
// ... data configuration
},
options: {
plugins: {
title: {
display: true,
text: 'Monthly Sales Data',
font: {
family: 'Arial, sans-serif',
size: 18,
weight: 'bold',
style: 'normal'
},
color: '#333',
padding: {
top: 10,
bottom: 20
}
}
}
}
});2. Legend Styles
javascript
const myChart = new Chart(ctx, {
type: 'bar',
data: {
// ... data configuration
},
options: {
plugins: {
legend: {
display: true,
position: 'top',
align: 'center',
labels: {
font: {
family: 'Arial, sans-serif',
size: 14,
weight: 'normal'
},
color: '#666',
padding: 10,
usePointStyle: true, // Use point style instead of square
pointStyle: 'circle'
}
}
}
}
});3. Tooltip Styles
javascript
const myChart = new Chart(ctx, {
type: 'bar',
data: {
// ... data configuration
},
options: {
plugins: {
tooltip: {
enabled: true,
backgroundColor: 'rgba(0, 0, 0, 0.8)',
titleColor: '#fff',
bodyColor: '#fff',
borderColor: '#333',
borderWidth: 1,
cornerRadius: 6,
displayColors: true,
font: {
family: 'Arial, sans-serif',
size: 12,
weight: 'normal'
},
padding: 10,
callbacks: {
title: function(tooltipItems) {
return 'Month: ' + tooltipItems[0].label;
},
label: function(context) {
return context.dataset.label + ': ' + context.parsed.y + ' ten thousand';
}
}
}
}
}
});Axis Styles
1. Basic Axis Configuration
javascript
const myChart = new Chart(ctx, {
type: 'bar',
data: {
// ... data configuration
},
options: {
scales: {
x: {
// X-axis title
title: {
display: true,
text: 'Month',
color: '#666',
font: {
family: 'Arial, sans-serif',
size: 14,
weight: 'bold'
}
},
// Tick marks
ticks: {
color: '#999',
font: {
family: 'Arial, sans-serif',
size: 12
},
callback: function(value, index, values) {
// Customize tick labels
return value + '月';
}
},
// Grid lines
grid: {
color: 'rgba(0, 0, 0, 0.1)',
lineWidth: 1
}
},
y: {
// Y-axis title
title: {
display: true,
text: 'Sales (ten thousand)',
color: '#666',
font: {
family: 'Arial, sans-serif',
size: 14,
weight: 'bold'
}
},
// Tick marks
ticks: {
color: '#999',
font: {
family: 'Arial, sans-serif',
size: 12
},
beginAtZero: true,
callback: function(value, index, values) {
// Add unit
return value + '万';
}
},
// Grid lines
grid: {
color: 'rgba(0, 0, 0, 0.1)',
lineWidth: 1
}
}
}
}
});2. Axis Position and Display
javascript
const myChart = new Chart(ctx, {
type: 'line',
data: {
// ... data configuration
},
options: {
scales: {
x: {
position: 'bottom', // 'top', 'bottom'
display: true, // Whether to display axis
reverse: false, // Whether to reverse axis
},
y: {
position: 'left', // 'left', 'right'
display: true,
min: 0, // Minimum value
max: 100, // Maximum value
ticks: {
stepSize: 10 // Tick step size
}
},
// Second Y-axis
y1: {
position: 'right',
display: true,
grid: {
drawOnChartArea: false // Don't draw grid lines in chart area
}
}
}
}
});Animation Effects
1. Basic Animation Configuration
javascript
const myChart = new Chart(ctx, {
type: 'bar',
data: {
// ... data configuration
},
options: {
animation: {
duration: 1000, // Animation duration (milliseconds)
easing: 'easeInOutQuart', // Easing function
delay: 0, // Delay time
loop: false // Whether to loop
// Animation property configuration
// colors: {
// duration: 1000,
// easing: 'easeInOutQuart'
// },
// numbers: {
// duration: 1000,
// easing: 'easeInOutQuart'
// }
}
}
});2. Custom Animation
javascript
const myChart = new Chart(ctx, {
type: 'bar',
data: {
// ... data configuration
},
options: {
animation: {
duration: 2000,
easing: 'linear',
onProgress: function(animation) {
// Callback during animation
console.log('Animation progress:', animation.currentStep / animation.numSteps);
},
onComplete: function(animation) {
// Callback when animation completes
console.log('Animation completed');
}
}
}
});Responsive Design
1. Basic Responsive Configuration
javascript
const myChart = new Chart(ctx, {
type: 'bar',
data: {
// ... data configuration
},
options: {
responsive: true, // Enable responsive
maintainAspectRatio: true, // Maintain aspect ratio
aspectRatio: 2, // Aspect ratio
// Responsive events
onResize: function(chart, size) {
console.log('Chart resized:', size);
}
}
});2. Media Query Styles
javascript
// Set different configurations based on screen size
const config = {
type: 'bar',
data: {
// ... data configuration
},
options: {
responsive: true,
plugins: {
legend: {
position: window.innerWidth < 768 ? 'bottom' : 'top'
}
},
scales: {
x: {
ticks: {
font: {
size: window.innerWidth < 768 ? 10 : 12
}
}
}
}
}
};
const myChart = new Chart(ctx, config);
// Listen to window size changes
window.addEventListener('resize', function() {
// Update chart configuration
myChart.options.plugins.legend.position = window.innerWidth < 768 ? 'bottom' : 'top';
myChart.options.scales.x.ticks.font.size = window.innerWidth < 768 ? 10 : 12;
myChart.update();
});Themes and Style Variants
1. Create Custom Theme
javascript
// Define theme configuration
const darkTheme = {
backgroundColor: '#222',
borderColor: '#444',
color: '#eee',
font: {
family: 'Arial, sans-serif',
size: 14,
weight: 'normal'
},
plugins: {
title: {
color: '#fff',
font: {
size: 18,
weight: 'bold'
}
},
legend: {
labels: {
color: '#ccc'
}
},
tooltip: {
backgroundColor: 'rgba(50, 50, 50, 0.9)',
titleColor: '#fff',
bodyColor: '#eee',
borderColor: '#666'
}
},
scales: {
x: {
ticks: {
color: '#ccc'
},
grid: {
color: 'rgba(255, 255, 255, 0.1)'
}
},
y: {
ticks: {
color: '#ccc'
},
grid: {
color: 'rgba(255, 255, 255, 0.1)'
}
}
}
};
// Apply theme
const myChart = new Chart(ctx, {
type: 'bar',
data: {
// ... data configuration
},
options: {
...darkTheme,
responsive: true,
scales: {
y: {
beginAtZero: true,
...darkTheme.scales.y
},
x: {
...darkTheme.scales.x
}
}
}
});2. Dynamic Theme Switching
javascript
// Define multiple themes
const themes = {
light: {
backgroundColor: '#fff',
color: '#333',
// ... other configurations
},
dark: {
backgroundColor: '#222',
color: '#eee',
// ... other configurations
}
};
// Use default theme when creating chart
let currentTheme = 'light';
const myChart = new Chart(ctx, {
type: 'bar',
data: {
// ... data configuration
},
options: {
...themes[currentTheme],
responsive: true
}
});
// Function to switch theme
function switchTheme(themeName) {
currentTheme = themeName;
Object.assign(myChart.options, themes[themeName]);
myChart.update();
}
// Usage example
// switchTheme('dark'); // Switch to dark themeComplete Example
Following is a complete example showing multiple style customization effects:
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chart.js Style Customization Example</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.chart-container {
position: relative;
height: 400px;
margin: 20px 0;
}
.controls {
text-align: center;
margin: 20px 0;
}
button {
margin: 5px;
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
.theme-selector {
margin: 20px 0;
text-align: center;
}
select {
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="container">
<h1 style="text-align: center;">Chart.js Style Customization Example</h1>
<div class="theme-selector">
<label for="themeSelect">Select Theme: </label>
<select id="themeSelect">
<option value="default">Default Theme</option>
<option value="dark">Dark Theme</option>
<option value="colorful">Colorful Theme</option>
</select>
</div>
<div class="controls">
<button onclick="toggleAnimation()">Toggle Animation</button>
<button onclick="changeColors()">Change Colors</button>
</div>
<div class="chart-container">
<canvas id="myChart"></canvas>
</div>
</div>
<script>
// Define theme configurations
const themes = {
default: {
backgroundColor: '#fff',
color: '#333',
plugins: {
title: {
color: '#333',
font: {
size: 18,
weight: 'bold'
}
},
legend: {
labels: {
color: '#666',
font: {
size: 14
}
}
},
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
titleColor: '#fff',
bodyColor: '#fff'
}
},
scales: {
x: {
ticks: {
color: '#666'
},
grid: {
color: 'rgba(0, 0, 0, 0.1)'
}
},
y: {
ticks: {
color: '#666'
},
grid: {
color: 'rgba(0, 0, 0, 0.1)'
}
}
}
},
dark: {
backgroundColor: '#222',
color: '#eee',
plugins: {
title: {
color: '#fff',
font: {
size: 18,
weight: 'bold'
}
},
legend: {
labels: {
color: '#ccc',
font: {
size: 14
}
}
},
tooltip: {
backgroundColor: 'rgba(50, 50, 50, 0.9)',
titleColor: '#fff',
bodyColor: '#eee',
borderColor: '#666'
}
},
scales: {
x: {
ticks: {
color: '#ccc'
},
grid: {
color: 'rgba(255, 255, 255, 0.1)'
}
},
y: {
ticks: {
color: '#ccc'
},
grid: {
color: 'rgba(255, 255, 255, 0.1)'
}
}
}
},
colorful: {
backgroundColor: '#f8f9fa',
color: '#333',
plugins: {
title: {
color: '#e74c3c',
font: {
size: 18,
weight: 'bold'
}
},
legend: {
labels: {
color: '#3498db',
font: {
size: 14
}
}
},
tooltip: {
backgroundColor: 'rgba(52, 152, 219, 0.9)',
titleColor: '#fff',
bodyColor: '#fff',
borderColor: '#2980b9'
}
},
scales: {
x: {
ticks: {
color: '#27ae60'
},
grid: {
color: 'rgba(39, 174, 96, 0.2)'
}
},
y: {
ticks: {
color: '#27ae60'
},
grid: {
color: 'rgba(39, 174, 96, 0.2)'
}
}
}
}
};
// Create chart
const ctx = document.getElementById('myChart').getContext('2d');
let myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June'],
datasets: [{
label: 'Product A Sales',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgba(255, 99, 132, 1)',
borderWidth: 2
}, {
label: 'Product B Sales',
data: [8, 15, 7, 12, 9, 6],
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 2
}]
},
options: {
...themes.default,
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: 'Product Sales Data Chart'
},
legend: {
position: 'top'
}
},
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: 'Sales (ten thousand)'
}
},
x: {
title: {
display: true,
text: 'Month'
}
}
},
animation: {
duration: 1000,
easing: 'easeInOutQuart'
}
}
});
// Theme switching
document.getElementById('themeSelect').addEventListener('change', function() {
const selectedTheme = this.value;
Object.assign(myChart.options, themes[selectedTheme]);
myChart.update();
});
// Toggle animation
let animationEnabled = true;
function toggleAnimation() {
animationEnabled = !animationEnabled;
myChart.options.animation.duration = animationEnabled ? 1000 : 0;
myChart.update();
}
// Change colors
function changeColors() {
const colors = [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 205, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
];
const borderColors = [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 205, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
];
// Randomly shuffle color arrays
shuffleArray(colors);
shuffleArray(borderColors);
myChart.data.datasets[0].backgroundColor = colors[0];
myChart.data.datasets[0].borderColor = borderColors[0];
myChart.data.datasets[1].backgroundColor = colors[1];
myChart.data.datasets[1].borderColor = borderColors[1];
myChart.update();
}
// Array random shuffle function
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
</script>
</body>
</html>Through this chapter's learning, you should have mastered how to customize Chart.js chart styles and appearance. In next chapter, we will explore Chart.js advanced features.