Want charts that feel alive in your app—without learning a whole new framework?
Chart.js makes interactive, responsive charts easy.
This step-by-step guide walks you through setup, building your first chart, and adding interactivity like tooltips and legends.
You’ll learn how to customize colors and scales, fix common rendering issues, and test results in the browser.
Each step includes a tiny checkpoint so you know you’re winning.
By the end you’ll have a working chart you can drop into any project and tweak.
Step-by-Step Setup to Begin Creating Charts with Chart.js

Chart.js is an open-source JavaScript library that draws charts inside the HTML5 <canvas> element. It scales responsively right out of the box. Before you write any chart code, you need to pull the library into your project and create a basic HTML structure. You can drop in a CDN link for quick testing, or install it through npm if you’re working in a bigger project with a build tool. Both methods load the same library. Pick whichever fits how you work.
Once the library’s loaded, create a <canvas> element in your HTML and give it a unique ID so your JavaScript can find it. Then grab that canvas element, get its 2D drawing context, and pass it to Chart.js with a configuration object. The config tells the library what kind of chart to draw and which data to show. Save the file and open it in a browser. You should see your first chart render instantly. If nothing shows up, check your browser’s console. Usually it means the canvas element is missing or the script didn’t load.
Here’s the full setup to get your first chart running:
-
Add Chart.js to your project by pasting a CDN script tag into your HTML
<head>or just before the closing</body>tag. Use<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>. Or runnpm install chart.jsand import it in your JavaScript file. -
Insert a
<canvas>element in your HTML body with a unique ID like<canvas id="myChart"></canvas>. You can set width and height attributes if you need a fixed size, but Chart.js handles responsiveness automatically. -
In your JavaScript file or a
<script>tag, select the canvas usingdocument.getElementById('myChart')and call.getContext('2d')to get the drawing context. Like this:const ctx = document.getElementById('myChart').getContext('2d');. -
Instantiate a new Chart by calling
new Chart(ctx, config), whereconfigis an object containing at leasttype(like'bar'or'line'),data(labels and datasets), and optionallyoptionsfor customization. -
Save your HTML file and open it in any modern browser. The chart should render immediately. If you’re using a local file, you might need a simple HTTP server if you run into CORS issues when loading external data later.
-
Verify the chart displays correctly. Right-click the canvas area and inspect it in DevTools to confirm the canvas element exists and has width and height attributes set by Chart.js. Check the console for any error messages if nothing appears.
Building Your First Chart.js Chart from Scratch

A basic Chart.js configuration needs three pieces: the chart type, a data object, and an optional options object. The data object always contains a labels array (the categories or x-axis values) and a datasets array, which holds one or more dataset objects. Each dataset includes a label (the series name), a data array of numbers matching the length of your labels, and styling properties like backgroundColor, borderColor, and borderWidth. If you have three labels, you need exactly three data points in each dataset.
When you create the chart, Chart.js reads the type field to decide which rendering logic to use. A line chart draws points connected by segments. A bar chart renders vertical or horizontal bars. The options object controls everything else: axis scales, legends, tooltips, animations. But you can skip it entirely for a minimal demo. The simplest working example uses type: 'line', two or three labels, one dataset with matching data values, and basic RGBA color strings like backgroundColor: 'rgba(255, 99, 132, 0.8)' and borderColor: 'rgba(255, 99, 132, 1)'.
Save the file, refresh your browser, and you should see a line chart with labeled points. If the chart looks cut off or too small, Chart.js is probably rendering it at the default canvas size. You can adjust the canvas element’s width and height in HTML, or let the library handle it automatically using the responsive option, which is enabled by default. From here, you can swap type: 'line' to type: 'bar' or type: 'pie' and watch the same data transform into a completely different visual.
Chart.js Basic Chart Types Explained with Step-by-Step Examples

Chart.js supports several core chart types out of the box, each suited to different kinds of data and comparison tasks. Line charts work well for trends over time. Bar charts compare categorical values side by side. Pie or doughnut charts show proportions within a whole. Scatter charts plot individual data points in two-dimensional space, while radar and polar area charts use radial axes for multi-variable comparisons. Switching between these types is as simple as changing the type property in your configuration and adjusting your dataset structure to match what each chart expects.
Line Chart
Line charts connect data points with segments and they’re perfect for showing trends or changes over time. Your dataset needs a data array of numbers and an optional fill property to shade the area under the line. Set tension: 0.4 to add a smooth curve instead of sharp angles between points. Colors work just like in other charts. borderColor controls the line itself, and backgroundColor fills the area if you enable fill: true. If you have thousands of points, Chart.js can automatically reduce them using data decimation. This keeps the chart responsive without losing the overall shape.
Bar Chart
Bar charts render vertical or horizontal bars for each data point, making them ideal for comparing categories. Your data array maps one bar per label. You can pass an array of colors to backgroundColor if you want each bar to have a different color. Just make sure the array length matches your data length. Use scales in the options object to control axis behavior, like setting beginAtZero: true on the y-axis so bars always start from zero. For horizontal bars, change type from 'bar' to 'horizontalBar' in Chart.js 2.x, or use indexAxis: 'y' in Chart.js 3.x and later.
Pie and Doughnut Charts
Pie and doughnut charts divide a circle into slices, where each slice represents a portion of the total. The main difference is that doughnut charts have a hollow center. Both use a single dataset with a data array of numbers, and Chart.js automatically calculates percentages. You can pass an array of colors to backgroundColor to give each slice its own color. Legends are especially useful here because slices don’t have space for long labels. If you need to show the value inside each slice, use a plugin or custom tooltip callbacks.
Scatter Chart
Scatter charts plot individual points on an x-y grid. They’re useful for showing correlations or distributions. Instead of a simple number array, each data point is an object with x and y properties. Like this: data: [{x: 10, y: 20}, {x: 15, y: 25}]. You control point appearance using pointBackgroundColor, pointBorderColor, and pointRadius. Scatter charts don’t draw lines by default, but you can enable them by setting showLine: true in the dataset. This chart type is great for visualizing relationships between two variables or spotting outliers in your data.
Customizing Your Chart.js Charts (Colors, Labels, Legends, Tooltips)

Chart.js gives you full control over how your charts look and behave through the options object. You can change colors for every element: bars, lines, points, backgrounds. Most styling properties accept either a single value or an array. If you pass an array of colors to backgroundColor, Chart.js assigns each value to the corresponding data point or slice. For consistent styling across multiple charts, you can set global font defaults like Chart.defaults.font.family = "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" before creating any chart instances.
Legends and tooltips are interactive by default and can be customized using the plugins section in your options. The legend lists all datasets and lets users toggle visibility by clicking. You can move it to the top, bottom, left, or right using plugins.legend.position. Adjust its font size with plugins.legend.labels.font.size. Tooltips appear when you hover over data points and display the label and value. You can change tooltip fonts, background colors, and padding, or even rewrite the entire tooltip using custom callbacks. Setting plugins.tooltip.titleFont.size: 18 and plugins.tooltip.bodyFont.size: 14 makes the title larger and the body smaller for better hierarchy.
Here are five common customization tasks you’ll use constantly:
- Colors: Set
backgroundColorandborderColorfor datasets using RGBA strings like'rgba(54, 162, 235, 1)'. Pass arrays to assign different colors per data point. - Fonts: Adjust font size, family, and weight using the
fontobject inside legend, title, tooltip, or axis label configs. Legend fonts default to size 16, tooltip titles to 18, and body text to 14. - Legends: Control placement with
plugins.legend.position(top, bottom, left, right) and toggle display withplugins.legend.display: true/false. Customize label colors and click behavior via callbacks. - Tooltips: Change tooltip background with
plugins.tooltip.backgroundColor: 'rgba(0, 0, 0, 0.8)', adjust padding, and usecallbacks.labelto format the displayed values or add extra information. - Layout and padding: Use
layout.paddingto add space around the chart inside the canvas. This prevents labels or legends from getting cut off at the edges.
Making Chart.js Charts Responsive and Controlling Canvas Behavior

Chart.js is responsive by default. It automatically redraws the chart when the browser window resizes. This works because the library listens for resize events and recalculates the canvas dimensions to fit its parent container. You don’t need to write any extra code for this. Just make sure the canvas element or its wrapper has a flexible width, like setting the parent div to width: 100% in CSS. The chart will scale to fill the available space while maintaining its aspect ratio.
If you need more control over sizing, use the maintainAspectRatio option. By default it’s set to true, which keeps the chart’s width-to-height ratio constant. Setting maintainAspectRatio: false lets the chart stretch to fill both dimensions of its container independently. This is useful when you want a chart to occupy a fixed height sidebar or dashboard panel. You can also override the aspect ratio itself using aspectRatio: 2, which makes the chart twice as wide as it is tall. Combine these options with CSS media queries to create charts that adapt layout rules at different screen sizes, like switching from a wide line chart on desktop to a taller, narrower version on mobile.
Working with Chart.js Data: JSON, CSV, External Files, and Dynamic Updates

Chart.js accepts data in multiple formats: plain arrays, arrays of objects, JSON from an API, or parsed CSV files. For simple demos, you can hard-code your labels and data arrays directly in the configuration object. When you need to load data from an external file or API, use JavaScript’s fetch() method to retrieve JSON, then extract the labels and values from the response. For CSV files, you’ll need a parsing library like PapaParse to convert rows into JavaScript objects before mapping them into Chart.js datasets.
Dynamic updates let you change chart data after the initial render without recreating the entire chart. After modifying the data.labels or data.datasets arrays, call chart.update() to trigger a re-render. Chart.js will animate the transition from the old values to the new ones. This pattern is perfect for real-time dashboards that pull fresh data every few seconds, or interactive filters that let users toggle categories on and off. You can also pass options to update() like chart.update('none') to skip animations and render instantly.
| Data Source | Method | Notes |
|---|---|---|
| JSON local file | fetch(‘data.json’).then(res => res.json()) | Parse JSON and map to labels/datasets arrays |
| JSON API | fetch(‘https://api.example.com/data’) | Same as local JSON; handle errors and loading states |
| CSV file | PapaParse.parse(file, config) | Returns array of objects; extract columns for labels and data |
| Arrays of objects | map() to extract properties | Useful when data comes from a database or form inputs |
| Dynamic updates | chart.update() | Call after changing data or options; animates transitions by default |
Creating Mixed Chart.js Charts and Using Plugins for Interactivity

Mixed charts let you combine different chart types on the same canvas, like overlaying a line on top of bars to show a trend alongside categorical data. You create a mixed chart by setting type: 'bar' (or any base type) at the top level, then overriding individual datasets with their own type property. One dataset might have type: 'line' while another uses type: 'bar'. Chart.js renders both in the same coordinate space, using shared axes and scales. This is especially useful for financial dashboards where you want to compare totals (bars) against averages or targets (lines).
Plugins extend Chart.js with features like zooming, panning, annotations, and custom data labels. The most popular is chartjs-plugin-zoom, which adds mouse wheel zooming and click-drag panning to any chart. After installing the plugin, enable it in your options with plugins.zoom.zoom.wheel.enabled: true and plugins.zoom.pan.enabled: true. You can also set zoom limits and reset buttons. Plugins hook into Chart.js lifecycle events, so they can modify rendering, add new elements, or respond to user interactions. Many plugins are open-source and maintained by the community, covering use cases from exporting charts as images to drawing threshold lines.
Common plugin use cases:
- Zooming and panning: chartjs-plugin-zoom lets users drill into time-series data by scrolling to zoom and dragging to pan. Set
hover: { mode: 'nearest' }to highlight the closest data point on hover. - Annotations: Draw horizontal or vertical lines, boxes, or labels on top of your chart to mark thresholds, goals, or events. Useful for highlighting important values or date ranges.
- Data labels: Display the exact value above each bar or point automatically, instead of requiring users to hover for tooltips. The chartjs-plugin-datalabels library handles this cleanly.
- Exporting and saving: Plugins can convert the canvas to a PNG or PDF, letting users download a snapshot of the chart for reports or presentations.
Fixing Common Chart.js Errors and Debugging Rendering Issues

The most frequent Chart.js error is “Cannot read property ‘getContext’ of null,” which means your JavaScript tried to access the canvas element before it loaded. This happens when your script runs before the DOM is ready. Fix it by moving your <script> tag to the end of the <body>, wrapping your code in a DOMContentLoaded event listener, or using defer on the script tag. If the canvas renders but stays blank, check the browser console for warnings. Often it’s a missing Chart.js script, a typo in the CDN URL, or a mismatch between the number of labels and data points.
Scale type mismatches cause weird axis behavior, like a line chart trying to use a category scale for numeric data. Make sure your scale type matches your data. Use 'linear' for continuous numbers, 'category' for strings, and 'time' for dates. If you see data points clumped at the edge or overlapping, you probably forgot to set beginAtZero: true on the axis, or the axis range is auto-calculated incorrectly. You can manually set min and max values in the scale options to force a specific range.
Here are five mistakes to check when your chart doesn’t work:
- Missing or undefined canvas context: Verify the canvas element exists in the HTML and your JavaScript selector matches the ID exactly. Log
ctxto the console to confirm it’s not null. - Chart.js script not loaded: Open the Network tab in DevTools and confirm the CDN request succeeded with a 200 status. If you installed via npm, check your import statement.
- Dataset and labels length mismatch: Count your labels and data arrays. If labels has 5 entries but data has 4, Chart.js might skip the last label or throw an error.
- Wrong scale type for your data: Trying to plot dates on a category scale or strings on a linear scale breaks axis rendering. Match your scale type to your data type.
- Typos in configuration keys: Chart.js silently ignores unknown options. Double-check spelling of
backgroundColor,borderColor,plugins, and other config keys. One extra letter breaks the entire option.
Final Words
You jumped straight into the setup: included Chart.js (CDN or npm), added a canvas, grabbed the 2D context, and instantiated a Chart. Then you built a line chart, learned how labels, datasets, and options fit together, and explored other chart types, styling, responsiveness, data loading, plugins, and debugging.
If something broke, check imports, the canvas id, and dataset lengths. chart.update() will redraw after data changes.
Now you can create charts with Chart.js step by step and turn raw numbers into clear visuals. Keep tinkering—your charts will get cleaner fast.
FAQ
Q: How to create a chart using js?
A: Creating a chart using JS involves including Chart.js (CDN or npm), adding a canvas element, getting its 2D context, then instantiating new Chart(ctx, config) and opening the page in a browser.
Q: How to create a chart within a chart?
A: Creating a chart within a chart means using mixed chart types or an inset overlay — add multiple datasets with different type fields, render a second canvas, or use a plugin to draw the inner chart.
Q: Can Chart.js create interactive charts?
A: Chart.js can create interactive charts: it offers built-in hover and tooltip interactions, click/hover callbacks, and supports plugins (like zoom or annotation) for pan, zoom, and custom interactions.
Q: Is chart.js based on D3?
A: Chart.js is not based on D3; Chart.js uses the HTML5 canvas and its own rendering API, while D3 is a lower-level DOM/SVG toolkit for data-driven document manipulation.

