search
HomeWeb Front-endCSS TutorialHow to Make a Line Chart With CSS

How to Make a Line Chart With CSS

The cornerstones of the dashboard are line charts, bar charts, and pie charts, which are essential components of any data visualization toolkit. Of course, you can use JavaScript chart libraries like SVG or Chart.js, or a complex tool like D3 to create these charts, but what if you don't want to load another library into a website that you already have performance-constrained?

There are a lot of articles on how to create bar charts, bar charts and pie charts that use CSS only, but if you only need a basic line chart, you are in bad luck. While CSS can "draw lines" using borders, etc., there is no clear way to draw from one point to another on the X and Y coordinate planes.

There is indeed a way! If you only need a simple line chart, you don't need to load large JavaScript libraries, or even use SVG. You can create everything you need with just some custom properties in CSS and HTML. However, it is important to remind you that this does involve some trigonometry. If that doesn't scare you, then let's get started!

Here are our goals:

Start at baseline

If you are creating a line chart by hand (like actually drawing lines on chart paper), you will first create points and then connect these points to form the lines. If you break down the process like this, you can recreate any basic line chart in CSS.

Suppose we have an array of data to display points on X and Y coordinate systems, where the day of the week is on the X axis and the numerical value represents the points on the Y axis.

 <code>[ { value: 25, dimension: "Monday" }, { value: 60, dimension: "Tuesday" }, { value: 45, dimension: "Wednesday" }, { value: 50, dimension: "Thursday" }, { value: 40, dimension: "Friday" } ]</code>

Let's create an unordered list to save our data points and apply some styles to them. Here is our HTML:


<li>
<li>
<li>
<li>
<li>

A few points to pay attention to here. First, we wrap everything in one<ul></ul> Among elements, this is a good way to semantic HTML, indicating that this is self-contained content, and can also be used if needed.<figcaption></figcaption> The added benefits. Second, please note that we store the value in a custom property called data-value , which is included in itself<div> In, the<code><div> Located in the list item in the unordered list. Why we use separate<code><div> Instead of putting the class and attributes in the list item itself? This will help us later when drawing lines.<p> Finally, note that we have an inline custom property on the parent element, which we call <code>--widget-size . We will use it in CSS, which will look like this:

 <code>/* 父元素*/ .css-chart { /* 图表边框*/ border-bottom: 1px solid; border-left: 1px solid; /* 高度,最初在HTML中定义*/ height: var(--widget-size); /* 如果图表周围有其他项目,则留出一些空间*/ margin: 1em; /* 删除任何填充,以便我们在元素内部有尽可能多的空间可以使用*/ padding: 0; position: relative; /* 图表宽度,在HTML中定义*/ width: var(--widget-size); } /* 包含数据点的无序列表,没有列表样式和间距*/ .line-chart { list-style: none; margin: 0; padding: 0; } /* 图表上的每个点,每个都是一个带浅色边框的12px圆圈*/ .data-point { background-color: white; border: 2px solid lightblue; border-radius: 50%; height: 12px; position: absolute; width: 12px; }</code>

The HTML and CSS above will give us this less exciting starting point:

Rendering data points

This doesn't look like a chart yet. We need a way to plot each data point on the respective X and Y coordinates on the chart to be generated. In our CSS we set .data-point class to use absolute positioning and set fixed width and height on its parent .css-chart container using custom properties. We can use it to calculate our X and Y positions.

Our custom properties set the chart height to 200px and in our value array the maximum is 60. If we set this data point to the highest point (200px) on the Y axis of the chart, then we can use the ratio of any value in the dataset to 60 and multiply it by 200 to get the Y coordinates of all points. Therefore, our maximum value of 60 will have a Y value that can be calculated like this:

 <code>(60 / 60) * 200 = 200px</code>

And our smallest value of 25 will calculate the Y value in the same way:

 <code>(25 / 60) * 200 = 83.33333333333334px</code>

It is easier to get the Y coordinates of each data point. If we spread the points evenly on the chart, we can divide the width of the chart (200px) by the number of values ​​in the data array (5) to get 40px. This means that the X coordinate of the first value will be 40px (you can leave margins for the left axis if we want), and the X coordinate of the last value will be 200px.

You just did the math operation! ?

Now, let's go to each of the list items<div> Add inline style. Our new HTML will become like this, where the inline style contains the calculated position of each point.<pre class="brush:php;toolbar:false"> </pre> <li> <div data-value="25" style="bottom: 83.33333333333334px; left: 40px;"></div> </li> <li> <div data-value="60" style="bottom: 200px; left: 80px;"></div> </li> <li> <div data-value="45" style="bottom: 150px; left: 120px;"></div> </li> <li> <div data-value="50" style="bottom: 166.66666666666669pxpx; left: 160px;"></div> </li> <li> <div data-value="40" style="bottom: 133.33333333333331px; left: 200px;"></div> </li> <p>Hey, this looks much better! But even if you can see what this is going on, you still can't really call it a line chart. no problem. We just need to use <em>a little</em> more math to complete our continuous point game. Check out the picture of the data points we rendered again. Can you see the triangles connecting them? If not, maybe the next image will help:</p> <p> Why is this important? Shhh, the answer is coming soon.</p> <h3 id="Rendering-line-segments"> Rendering line segments</h3> <p> Have you seen the triangle now? They are more than just ordinary triangles. They are our best triangles (for our purposes) because they are <strong>right angle triangles</strong> ! When we calculate the Y coordinates of the data point earlier, we are also calculating the length of one side of a right triangle ("Run" if you think of it as a ladder). If we calculate the difference in the X coordinate from one point to another, this will tell us the length of the other side of the right triangle (i.e. the "rise" of the step). With these two pieces of information, we can calculate the length of the magical bevel, which turns out is exactly what we need to draw onto the screen to connect our points and make a real line chart.</p> <p> For example, let's look at the second and third points on the chart.</p> <p> The Y value of the second data point is 200 and the Y value of the third data point is 150, so the opposite side length of the triangle connecting them is 200 minus 150, i.e. 50. It has a 40-pixel-long neighbor (the spacing we leave between each point).</p> <p> This means that the length of the hypotenuse is 50 squares plus 40 squares of squares, i.e. 64.03124237432849.</p> <p> Let's create another one within each list item in the chart<code><div> , it will act as the hypotenuse of the triangle drawn from that point. Then, we will be in this new<code><div> Set an inline custom property on which contains the length of the bevel.<p> At the same time, our line segments need to know their correct X and Y coordinates, so let's remove the inline style from <code>.data-point element, but in its parent element (<li> Add CSS custom attributes to element). Let's creatively refer to these properties --x and --y . Our data points do not need to know the bevel (the length of the segment), so we can add CSS custom properties for the bevel length directly to .line-segment . So now our HTML will look like this:

We need to update the CSS to locate the data points with these new custom properties and set up the new .line-segment we add to the tag<div> Style:<pre class="brush:php;toolbar:false"> &lt;code&gt;.data-point { /* 和以前一样*/ bottom: var(--y); left: var(--x); } .line-segment { background-color: blue; bottom: var(--y); height: 3px; left: var(--x); position: absolute; width: calc(var(--hypotenuse) * 1px); }&lt;/code&gt;</pre> <p> OK, we have segments now, but that's not what we want at all. To get a line chart with normal function, we need to apply the conversion. But first, let's fix some issues.</p> <p> First, our segment aligns with the bottom of the data point, but we want the origin of the segment to be in the center of the data point circle. We can solve this problem by quickly changing <code>.data-point style CSS. We need to adjust their X and Y positions to take into account both the size of the data points and their borders and the width of the line segments.

 <code>.data-point { /* ... */ /* 数据点的半径为8px,线段的宽度为3px,  因此我们将差值分成两半,以使数据点位于线段原点的中心*/ bottom: calc(var(--y) - 6.5px); left: calc(var(--x) - 9.5px); }</code>

Second, our line segments are rendered at the top of the data point rather than behind it. We can solve this problem by putting the line segment first in HTML:

Applying transformation, it's great

We're almost done. We only need to do the last bit of math. Specifically, we need to find a measure of the angle opposite to the opposite side of a right triangle and then rotate our segments by the same degree.

How do we do it? Trigonometry! You may also remember little memory tips for how to calculate sine, cosine, and tangent:

    <li> SOH (sine = opposite side/oblique side) <li> CAH (cosine = adjacent/oblique) <li> TOA (tangent = opposite side/near side)

You can use either because we know the length of all three sides of a right triangle. I chose the sine, so this leaves us with this equation:

 <code>sin(x) = 对边/ 斜边</code>

The answer to this equation will tell us how to rotate each line segment to connect it to the next data point. We can do this quickly using Math.asin(Opposite / Hypotenuse) in JavaScript. But it gives the answer in radians, so we need to multiply the result by (180 / Math.PI) .

Using our second data point example above, we have calculated that the paired edge length is 50 and the beveled edge length is 64.03124237432849, so we can rewrite our equation as:

 <code>sin(x) = 50 / 64.03124237432849 = 51.34019174590991</code>

This is the angle we are looking for! We need to solve the equation for each data point and then pass that value to our .line-segment element as a CSS custom property. This will make our HTML look like this:

And here we can apply these properties in CSS:

 <code>.line-segment { /* ... */ transform: rotate(calc(var(--angle) * 1deg)); width: calc(var(--hypotenuse) * 1px); }</code>

Now, when we render it, we finally get the line chart we've been waiting for using CSS only.

Important Note: When you calculate the value of the opposite edge ("rise"), make sure to calculate it as "Y position of the current data point" minus "Y position of the next data point". When the value of the next data point is greater than the current data point (higher on the chart), this will result in a negative value, which will result in a negative rotation. This is how we make sure the lines are tilted upwards.

When to use such charts

This approach is perfect for simple static websites or dynamic websites that use server-side generated content. Of course, it can also be used on sites with dynamically generated content on the client side, but then you go back to running JavaScript on the client side. The CodePen at the top of this article shows an example of how the client generates this line chart dynamically.

The CSS calc() function is very useful, but it cannot calculate sine, cosine, and tangent for us. This means you have to calculate your values ​​manually, or write a quick function (client or server side) to generate the required values ​​(X, Y, bevel and angle) for our CSS custom properties.

I know some of you went through this process and if you needed a script to calculate the value, it felt like it wasn't pure CSS - that's fair. The key is that all the graph rendering is done in CSS. The points and lines connecting them are all done using HTML elements and CSS, and they work perfectly even in static rendering environments without JavaScript enabled. Perhaps more importantly, you can render a simple line chart on your page without downloading another bloated library.

Potential improvements

Like anything, we can always do something to take things to the next level. In this case, I think this approach can be improved through three aspects.

Responsive

The method I outlined uses a fixed size for chart sizes, which is exactly what we don't want to see in responsive design. If we can run JavaScript on the client, we can resolve this limitation. Instead of hardcoded the chart size, set a CSS custom property (remember our --widget-size property?), do all the calculations based on it, and update that property using some kind of container query or window resize listener when the container or window is initially displayed or resized.

Tooltips

We can add a ::before pseudo-element to .data-point to display the data-value information it contains when hovering over a data point. This is a nice addition and helps turn our simple chart into a finished product.

Axis

Please note that the chart axes are not marked? We can distribute labels on the axes representing the highest value, zero, and any number of points between them.

Margins

I'm trying to make the numbers in this article as simple as possible, but in the real world you might want to include some margins in the chart so that the data points don't overlap with the extreme edges of the container. This may be simple, just subtract the width of the data point from the range of the y-coordinate. For X coordinates, you can also subtract the width of the data point from the total width of the chart similarly before dividing the chart into equal areas.

That's it! We just looked at a way to chart in CSS, and we don't even need libraries or other third-party dependencies to make it work. ?

The above is the detailed content of How to Make a Line Chart With CSS. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
@keyframes vs CSS Transitions: What is the difference?@keyframes vs CSS Transitions: What is the difference?May 14, 2025 am 12:01 AM

@keyframesandCSSTransitionsdifferincomplexity:@keyframesallowsfordetailedanimationsequences,whileCSSTransitionshandlesimplestatechanges.UseCSSTransitionsforhovereffectslikebuttoncolorchanges,and@keyframesforintricateanimationslikerotatingspinners.

Using Pages CMS for Static Site Content ManagementUsing Pages CMS for Static Site Content ManagementMay 13, 2025 am 09:24 AM

I know, I know: there are a ton of content management system options available, and while I've tested several, none have really been the one, y'know? Weird pricing models, difficult customization, some even end up becoming a whole &

The Ultimate Guide to Linking CSS Files in HTMLThe Ultimate Guide to Linking CSS Files in HTMLMay 13, 2025 am 12:02 AM

Linking CSS files to HTML can be achieved by using elements in part of HTML. 1) Use tags to link local CSS files. 2) Multiple CSS files can be implemented by adding multiple tags. 3) External CSS files use absolute URL links, such as. 4) Ensure the correct use of file paths and CSS file loading order, and optimize performance can use CSS preprocessor to merge files.

CSS Flexbox vs Grid: a comprehensive reviewCSS Flexbox vs Grid: a comprehensive reviewMay 12, 2025 am 12:01 AM

Choosing Flexbox or Grid depends on the layout requirements: 1) Flexbox is suitable for one-dimensional layouts, such as navigation bar; 2) Grid is suitable for two-dimensional layouts, such as magazine layouts. The two can be used in the project to improve the layout effect.

How to Include CSS Files: Methods and Best PracticesHow to Include CSS Files: Methods and Best PracticesMay 11, 2025 am 12:02 AM

The best way to include CSS files is to use tags to introduce external CSS files in the HTML part. 1. Use tags to introduce external CSS files, such as. 2. For small adjustments, inline CSS can be used, but should be used with caution. 3. Large projects can use CSS preprocessors such as Sass or Less to import other CSS files through @import. 4. For performance, CSS files should be merged and CDN should be used, and compressed using tools such as CSSNano.

Flexbox vs Grid: should I learn them both?Flexbox vs Grid: should I learn them both?May 10, 2025 am 12:01 AM

Yes,youshouldlearnbothFlexboxandGrid.1)Flexboxisidealforone-dimensional,flexiblelayoutslikenavigationmenus.2)Gridexcelsintwo-dimensional,complexdesignssuchasmagazinelayouts.3)Combiningbothenhanceslayoutflexibilityandresponsiveness,allowingforstructur

Orbital Mechanics (or How I Optimized a CSS Keyframes Animation)Orbital Mechanics (or How I Optimized a CSS Keyframes Animation)May 09, 2025 am 09:57 AM

What does it look like to refactor your own code? John Rhea picks apart an old CSS animation he wrote and walks through the thought process of optimizing it.

CSS Animations: Is it hard to create them?CSS Animations: Is it hard to create them?May 09, 2025 am 12:03 AM

CSSanimationsarenotinherentlyhardbutrequirepracticeandunderstandingofCSSpropertiesandtimingfunctions.1)Startwithsimpleanimationslikescalingabuttononhoverusingkeyframes.2)Useeasingfunctionslikecubic-bezierfornaturaleffects,suchasabounceanimation.3)For

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.