How to Make a Doughnut Chart Using CSS

For a while now, I've been working on filling in 72% of a circle with a hole cut out of the middle. Throughout this process, I have been consulting different resources - like this method for calculating and this one for other aspects. However, I’ve been facing an issue with negative cosine calculations that prevent me from achieving the desired arc. My understanding of HTML is limited, so I believe the problem may be my own misunderstanding. Any advice or guidance would be greatly appreciated!

Below is an example of the code demonstrating a 12% version which I managed to get working. While attempting a 72% version has proven challenging, I've done my best to replicate it as closely as possible.

<svg focusable="false" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" tabindex="-1" height="60%" width="60%" viewBox="-5  -5 410 410" style="display: block; fill: transparent; position: absolute; right: 15px; bottom: 15px;">
  <circle aria-hidden="true" tabindex="-1" cx="200" cy="200" r="200" style="stroke: rgb(139, 138, 175); stroke-width: 5px;"></circle>
  <path aria-hidden="true" tabindex="-1" d="M 200 0 A 200 200 0 1 1 199.8000000333334 0.00009999999167575879 L 199.87500002083337 75.0000624999948 A 125 125 0 1 0 200 75 Z" fill="#FFFFFF"></path>
  <path aria-hidden="true" tabindex="-1" d="M 200 0 A 200 200 0 0 1 199.80000003333333 0.00009999999167575879 L 199.87500002083334 75.0000624999948 A 125 125 0 0 0 200 75 Z" fill="#00ACC8"></path>
  <path aria-hidden="true" tabindex="-1" d="M 200 0 A 200 200 0 0 1 336.76355902984756 54.06943801420687 L 285.4772243936547 108.79339875887929 A 125 125 0 0 0 200 75 Z" fill="#00ACC8"></path>
  <circle aria-hidden="true" tabindex="-1" cx="200" cy="200" r="125" style="stroke: rgb(139, 138, 175); stroke-width: 2.5px; fill: transparent;"></circle><text aria-hidden="true" tabindex="-1" x="50%" y="50%" dy="7%" style="text-anchor: middle; font-weight: bold; font-size: 115px; fill: rgb(70, 112, 125);">12</text>
</svg>

Answer №1

Exploring a unique approach to customizing the donut chart through CSS manipulation, diverging from the conventional method usually utilized for pie charts by incorporating the stroke-dasharray property on a circular element.

text {
  text-anchor: middle;
  dominant-baseline: middle;
  font-weight: bold;
  font-size: 30px;
  fill: rgb(70, 112, 125);
}

circle.bar {
  stroke-dasharray: 0 100;
}

circle.p25 {
  stroke-dasharray: 25 100;
}

circle.p33 {
  stroke-dasharray: 33 100;
}

circle.p50 {
  stroke-dasharray: 50 100;
}
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" tabindex="-1" width="200" viewBox="0 0 100 100">
  <circle class="bar" cx="50" cy="50" r="40" stroke="#00ACC8" stroke-width="16" fill="none" pathLength="100" transform="rotate(-90 50 50)"/>
  <circle cx="50" cy="50" r="48" stroke="rgb(139, 138, 175)" stroke-width="1" fill="none" />
  <circle cx="50" cy="50" r="32" stroke="rgb(139, 138, 175)" stroke-width="1" fill="none" />
  <text aria-hidden="true" tabindex="-1" x="50" y="50">0</text>
</svg>

<svg focusable="false" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" tabindex="-1" width="200" viewBox="0 0 100 100">
  <circle class="bar p25" cx="50" cy="50" r="40" stroke="#00ACC8" stroke-width="16" fill="none" pathLength="100" transform="rotate(-90 50 50)"/>
  <circle cx="50" cy="50" r="48" stroke="rgb(139, 138, 175)" stroke-width="1" fill="none" />
  <circle cx="50" cy="50" r="32" stroke="rgb(139, 138, 175)" stroke-width="1" fill="none" />
  <text aria-hidden="true" tabindex="-1" x="50" y="50">25</text>
</svg>

<svg focusable="false" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" tabindex="-1" width="200" viewBox="0 0 100 100">
  <circle class="bar p33" cx="50" cy="50" r="40" stroke="#00ACC8" stroke-width="16" fill="none" pathLength="100" transform="rotate(-90 50 50)"/>
  <circle cx="50" cy="50" r="48" stroke="rgb(139, 138, 175)" stroke-width="1" fill="none" />
  <circle cx="50" cy="50" r="32" stroke="rgb(139, 138, 175)" stroke-width="1" fill="none" />
  <text aria-hidden="true" tabindex="-1" x="50" y="50">33</text>
</svg>

Delving into the significance of utilizing CSS for chart control and presenting an innovative version integrated with JavaScript functionalities:

document.forms.form01.range.addEventListener('change', e => {
  document.getElementById('bar').setAttribute('stroke-dasharray', `${e.target.value} 100`);
  document.getElementById('text').textContent = e.target.value;
});
text {
  text-anchor: middle;
  dominant-baseline: middle;
  font-weight: bold;
  font-size: 30px;
  fill: rgb(70, 112, 125);
}
<form name="form01">
  <input type="range" name="range" min="0" max="100" value="25"/>
</form>

<svg focusable="false" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" tabindex="-1" width="200" viewBox="0 0 100 100">
  <circle id="bar" cx="50" cy="50" r="40" stroke="#00ACC8" stroke-width="16" stroke-dasharray="25 100" fill="none" pathLength="100" transform="rotate(-90 50 50)"/>
  <circle cx="50" cy="50" r="48" stroke="rgb(139, 138, 175)" stroke-width="1" fill="none" />
  <circle cx="50" cy="50" r="32" stroke="rgb(139, 138, 175)" stroke-width="1" fill="none" />
  <text id="text" aria-hidden="true" tabindex="-1" x="50" y="50">25</text>
</svg>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Eliminating the 'white-space' surrounding concealed images

I am currently working on a project where I have a list of images that need to be hidden or shown based on the click event of specific <li> elements. While I have managed to achieve this functionality successfully, I am facing an issue with white spa ...

Is the card-columns class not available in Bootstrap 5.0? Are there any other alternatives provided by Bootstrap besides using CSS media queries and flex column?

While exploring Bootstrap 5.0, I noticed that the card-columns class was missing and there is no mention of it or its alternative in the Bootstrap 5.0 documentation. However, it can still be found in the Bootstrap 4.6 documentation. I understand that usin ...

CSS: Navigation links at the bottom of the page

I am looking to design a menu where all the menu items are aligned at the bottom, even if they span across multiple lines. ul { list-style-type: none; margin: 0; padding: 0; overflow: hidden; background-color: ...

The counter variable does not function properly within a setInterval function

I have encountered an issue with my scroll-counter variable inside the setInterval function. It increments by 1 each time the setInterval function runs, which is supposed to happen 20 times before stopping. However, I noticed that the value of this variabl ...

Can a website be designed to render consistently across all browsers without relying on a CSS reset?

Is it possible to create a website that renders well across all browsers without using CSS reset? Should CSS reset be used for websites of all sizes - small, one-page, large? Is it better to write all the CSS without a reset and only address necessary rend ...

Exploring the world of web scraping using Scrapy, Python, and a JavaScript-based website all in one

Hello, I am attempting to scrape the website using the following script: script.py import scrapy from scrapy.crawler import CrawlerProcess from threading import Thread class CourtSpider(scrapy.Spider): name = 'full_page' allowed_domai ...

Issues with Datepicker functionality in Bootstrap 5 are causing it to malfunction or not display

I am having trouble incorporating a timepicker on my webpage with bootstrap 5. The calendar feature isn't loading properly, preventing me from selecting any dates. I'm unsure if the issue lies with an error on my end or if the plugin isn't c ...

Employing JavaScript to display or conceal a <div> element while scrolling

I'm looking to create a customized sticky navigation bar through Javascript, but I have never written my own code in this language before. My approach involves implementing two sticky navigation bars that appear and disappear based on scrolling behav ...

Displaying JSON keys and values individually on an HTML page

Looking to display a JSON array in HTML using ngFor TypeScript : import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-ng-for', templateUrl: './ng-for.component.html', styleUrls: ['./ng-for ...

Organizing grid elements within the popper component

I am struggling to align the labels of options in the AutoComplete component with their respective column headers in the popper component: https://i.stack.imgur.com/0VMLe.png const CustomPopper = function (props: PopperProps) { co ...

Ensuring the accuracy of HTML sliders

I am just starting out with programming and currently working on an online experiment using Django. In our experiment, sliders are being used extensively as input devices. We are trying to figure out a way to validate the sliders to ensure that participan ...

Searching for the name of dynamically generated input fields using jQuery

I have a straightforward form featuring radio buttons <form> <input type="radio" name="radio_1" value="1" />Radio 1 <input type="radio" name="radio_1" value="2" />Radio 2 <input type="radio" name="radio_1" value="3" />Radio 3 </ ...

Creating a hover effect in CSS that applies to neighboring elements with similar attributes

My table is created using a struts2 iterator and has variable length and content. It looks something like this: <table> <tr class="odd" machineId="1" parameterId="1"><td></td></tr> <tr class="even" machineId="1" pa ...

What measures can I take to ensure that users cannot tamper with the PayPal code?

I've integrated a "Pay Now" button from Paypal onto my website. However, there is an issue where users can easily alter the payment amount before proceeding. Below is the code PayPal has provided: <form action="https://www.paypal.com/cgi-bin/webs ...

Looking to find the video code in the page source and figure out how to get the video to play

I have a requirement where I must embed the video code directly in a blog post. After figuring out the necessary code for the video and saving it in a html file named video.html, I encountered an issue when trying to upload the file to the blog. Only the ...

Creating a personalized webview in Appgyver Steroids: A step-by-step guide

I am planning to design the following layout: The main screen will display a web page There should be a sidebar on the left side The sidebar can be accessed by clicking on a 'hamburger' icon in the app header Currently, my app structure look ...

How can I prevent StateHasChanged() from affecting all open browsers in a Blazor Server-Side application?

Hey there, I'm new to Blazor but familiar with C#. This is my first time asking a question here so please bear with me. :) I am working on a Blazor server-side application where users can enter information and validate it based on server data. So far ...

What is the best way to incorporate white-space:normal within the text of a jQuery Mobile grid button?

Below is the code for my jQuery Mobile Grid buttons: <div class="ui-grid-b my-breakpoint"> <div class="ui-block-a"><button type="button" data-theme="c"> <img src="res/icon/android/business.png" height="45"><br>Business</ ...

manipulating child element's innerHTML with javascript

Is there a way to change my icon from expand_more to expand_less in the code below? <li class="dropdown-bt" onclick="dropdown('content');"> <a>dropdown-content <i class="material-icons">expand_more</i></a> </ ...

Is there a way to left-align these items?

I currently have 10 divs arranged side by side. I am trying to align the last divs to the left instead of center, but the solutions I found so far are not working. I've checked Bootstrap's documentation and tried using <div class="d-flex ...