{"id":326391,"date":"2020-12-02T07:28:56","date_gmt":"2020-12-02T15:28:56","guid":{"rendered":"https:\/\/css-tricks.com\/?p=326391"},"modified":"2020-12-07T08:18:07","modified_gmt":"2020-12-07T16:18:07","slug":"how-to-make-an-area-chart-with-css","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/how-to-make-an-area-chart-with-css\/","title":{"rendered":"How to Make an Area Chart With CSS"},"content":{"rendered":"\n

You might know a few ways to create charts with pure CSS. Some of them are covered here on CSS-Tricks<\/a>, and many others can be found on CodePen<\/a>, but I haven\u2019t seen many examples of \u201carea charts\u201d (imagine a line chart with the bottom area filled in), particularly any in HTML and CSS alone. In this article, we’ll do just that, using a semantic and accessible HTML foundation.<\/p>\n\n\n\n\n\n\n\n

\"A<\/figure>\n\n\n

Let\u2019s start with the HTML<\/h3>\n\n\n

To simplify things, we will be using <ul><\/code> tags as wrappers and <li><\/code> elements for individual data items. You can use any other HTML tag in your project, depending on your needs.<\/p>\n\n\n\n

<ul class=\"area-chart\">\n  <li> 40% <\/li>\n  <li> 80% <\/li>\n  <li> 60% <\/li>\n  <li> 100% <\/li>\n  <li> 30% <\/li>\n<\/ul><\/code><\/pre>\n\n\n\n

CSS can’t retrieve the inner HTML text, that is why we will be using CSS custom properties to pass data to our CSS. Each data item will have a --start<\/code> and an --end<\/code> custom properties.<\/p>\n\n\n\n

<ul class=\"area-chart\">\n  <li style=\"--start: 0.1; --end: 0.4;\"> 40% <\/li>\n  <li style=\"--start: 0.4; --end: 0.8;\"> 80% <\/li>\n  <li style=\"--start: 0.8; --end: 0.6;\"> 60% <\/li>\n  <li style=\"--start: 0.6; --end: 1.0;\"> 100% <\/li>\n  <li style=\"--start: 1.0; --end: 0.3;\"> 30% <\/li>\n<\/ul><\/code><\/pre>\n\n\n

Here\u2019s what we need to consider\u2026<\/h3>\n\n\n

There are several design principles we ought to consider before moving into styling:<\/p>\n\n\n\n

  • Units data:<\/strong> We will be using unit-less data in our HTML (i.e. no px<\/code>, em<\/code> , rem<\/code> , %<\/code> or any other unit). The --start<\/code> and --end<\/code> custom properties will be numbers between 0 and 1.<\/li>
  • Columns width:<\/strong> We won’t set a fixed width<\/code> for each <li><\/code> element. We won’t be using %<\/code> either, as we don’t know how many items are there. Each column width will be based on the main wrapper width, divided by the total number of data items. In our case, that\u2019s the width of the <ul><\/code> element divided by the number of <li><\/code> elements.<\/li>
  • Accessibility:<\/strong> The values inside each <li><\/code> is optional and only the --start<\/code> and --end<\/code> custom properties are required. Still, it\u2019s best to include some sort of text or value for screen readers and other assistive technologies to describe the content.<\/li><\/ul>\n\n\n

    Now, let\u2019s start styling!<\/h3>\n\n\n

    Let’s start with general layout styling first. The chart wrapper element is a flex container, displaying items in a row, stretching each child element so the entire area is filled.<\/p>\n\n\n\n

    .area-chart {\n  \/* Reset *\/\n  margin: 0;\n  padding: 0;\n  border: 0;\n\n  \/* Dimensions *\/\n  width: 100%;\n  max-width: var(--chart-width, 100%);\n  height: var(--chart-height, 300px);\n\n  \/* Layout *\/\n  display: flex;\n  justify-content: stretch;\n  align-items: stretch;\n  flex-direction: row;\n}<\/code><\/pre>\n\n\n\n

    If the area chart wrapper is a list, we should remove the list style to give us more styling flexibility.<\/p>\n\n\n\n

    ul.area-chart,\nol.area-chart {\n  list-style: none;\n}<\/code><\/pre>\n\n\n\n

    This code styles all of the columns in the entire chart. With bar charts<\/strong> it’s simple: we use background-color<\/code> and height<\/code> for each column. With area char<\/strong>ts<\/strong> we are going to use the clip-path<\/code> property to set the region that should be shown.<\/p>\n\n\n\n

    First we set up each column:<\/p>\n\n\n\n

    .area-chart > * {\n  \/* Even size items *\/\n  flex-grow: 1;\n  flex-shrink: 1;\n  flex-basis: 0;\n\n  \/* Color *\/\n  background: var(--color, rgba(240, 50, 50, .75));\n}<\/code><\/pre>\n\n\n\n

    To create a rectangle covering the entire<\/em> area, we will reach for the clip-path<\/code> property and use its polygon()<\/code> function containing the coordinates of the area. This basically doesn\u2019t do anything at the moment because the polygon covers everything:<\/p>\n\n\n\n

    .area-chart > * {\n  clip-path: polygon(\n    0% 0%,     \/* top left *\/\n    100% 0%,   \/* top right *\/\n    100% 100%, \/* bottom right *\/\n    0% 100%    \/* bottom left *\/\n  );\n}<\/code><\/pre>\n\n\n\n

    Now for the best part!<\/p>\n\n\n\n

    To show just part of the column, we clip it to create that area chart-like effect. To show just the area we want, we use the --start<\/code> and --end<\/code> custom properties inside the clip-path<\/code> polygon:<\/p>\n\n\n\n

    .area-chart > * {\n  clip-path: polygon(\n    0% calc(100% * (1 - var(--start))),\n    100% calc(100% * (1 - var(--end))),\n    100% 100%,\n    0% 100%\n  );\n}<\/code><\/pre>\n\n\n\n

    Seriously, this one bit of CSS does all<\/em> of the work. Here\u2019s what we get:<\/p>\n\n\n\n