I know you can make a circle in CSS using the border radius hack. But is there any way to make them have segments like this picture? Is there a way of doing this through HTML and CSS but not JS?
Yes, you can get such slices of custom angles using either one of the following two methods:
- If you don't need the slices to be elements themselves, the you can simply do it with one element and linear gradients - see this rainbow wheel I did last month.
- If you need the slices to be elements themselves, then you can do it by chaining rotate and skew transforms - see this circular menu I did a while ago.
For #2, see also this very much simplified example I did right now.
.pie {
overflow:hidden;
position: relative;
margin: 1em auto;
border: dashed 1px;
padding: 0;
width: 32em; height: 32em;
border-radius: 50%;
list-style: none;
}
.slice {
overflow: hidden;
position: absolute;
top: 0; right: 0;
width: 50%; height: 50%;
transform-origin: 0% 100%;
}
.slice:first-child {
transform: rotate(15deg) skewY(-22.5deg);
}
.slice-contents {
position: absolute;
left: -100%;
width: 200%; height: 200%;
border-radius: 50%;
background: lightblue;
}
.slice:first-child .slice-contents {
transform: skewY(22.5deg); /* unskew slice contents */
}
.slice:hover .slice-contents { background: violet; } /* highlight on hover */
<ul class='pie'>
<li class='slice'>
<div class='slice-contents'></div>
</li>
<!-- you can add more slices here -->
</ul>
Yes you can: http://jsfiddle.net/elias94xx/3rx7w/, http://jsfiddle.net/elias94xx/3rx7w/2/
#chart {
width: 0;
height: 0;
border-right: 60px solid purple;
border-top: 60px solid transparent;
border-left: 60px solid transparent;
border-bottom: 60px solid transparent;
border-radius: 60px;
-moz-border-radius: 60px;
-webkit-border-radius: 60px;
}
<div id="chart"></div>
.chart {
position: absolute;
width: 0;
height: 0;
border-radius: 60px;
-moz-border-radius: 60px;
-webkit-border-radius: 60px;
}
#chart1 {
border-right: 60px solid red;
border-top: 60px solid transparent;
border-left: 60px solid transparent;
border-bottom: 60px solid transparent;
}
#chart2 {
border-right: 60px solid transparent;
border-top: 60px solid green;
border-left: 60px solid transparent;
border-bottom: 60px solid transparent;
}
#chart3 {
border-right: 60px solid transparent;
border-top: 60px solid transparent;
border-left: 60px solid blue;
border-bottom: 60px solid transparent;
}
#chart4 {
border-right: 60px solid transparent;
border-top: 60px solid transparent;
border-left: 60px solid transparent;
border-bottom: 60px solid yellow;
}
<div id="chart1" class="chart"></div>
<div id="chart2" class="chart"></div>
<div id="chart3" class="chart"></div>
<div id="chart4" class="chart"></div>
Source: http://www.paulund.co.uk/how-to-create-different-shapes-in-css
You can use html li
element and some css transform
to represent each slice of the circle.
The tricky part is the transform
. In this case I've divided the circle into 5 slices.
The calculation is the following.
360/5=72 -> rotate
72+90=162 -> skewY
.sliceWrapper {
position: relative;
border: 1px solid black;
padding: 0;
width: 200px;
height: 200px;
border-radius: 50%;
list-style: none;
overflow: hidden;
}
.slice {
position: absolute;
left: -100%;
width: 200%;
height: 200%;
}
li {
overflow: hidden;
position: absolute;
top: -50%;
right: -50%;
width: 100%;
height: 100%;
transform-origin: 0% 100%;
}
li:first-child {
transform: rotate(0deg) skewY(162deg);
}
li:nth-child(2) {
transform: rotate(72deg) skewY(162deg);
}
li:nth-child(3) {
transform: rotate(144deg) skewY(162deg);
}
li:nth-child(4) {
transform: rotate(216deg) skewY(162deg);
}
li:nth-child(5) {
transform: rotate(288deg) skewY(162deg);
}
li:first-child .slice {
background: green;
}
li:nth-child(2) .slice {
background: tomato;
}
li:nth-child(3) .slice {
background: aqua;
}
li:nth-child(4) .slice {
background: yellow;
}
li:nth-child(5) .slice {
background: blue;
}
<ul class="sliceWrapper">
<li>
<div class="slice"></div>
</li>
<li>
<div class="slice"></div>
</li>
<li>
<div class="slice"></div>
</li>
<li>
<div class="slice"></div>
</li>
<li>
<div class="slice"></div>
</li>
</ul>
You can use a conic gradient
Conic gradients basically go around the shape, like a circle, from 0° to 360°.
Here is a basic conic gradient, with a circle:
div {
width: 500px;
height: 500px;
border-radius: 9999px;
background: red; /* fallback */
background: conic-gradient(red, orange, yellow, green, blue, purple);
}
<div></div>
Using color stops, we can then, magically, turn it into segments:
div {
width: 500px;
height: 500px;
border-radius: 9999px;
background: red; /* fallback */
background: conic-gradient(red 10%, orange 10%, orange 30%, yellow 30%, yellow 50%, green 50%, green 60%, blue 60%, blue 70%, purple 70%);
}
<div></div>
Optionally, if we only want one slice, we can now change this so we only have one colour, and now we're good to go :)
div {
width: 500px;
height: 500px;
border-radius: 9999px;
background: red; /* fallback */
background: conic-gradient(#0000 40%, red 40%, red 70%, #0000 70%);
}
<div></div>
body {
padding-top: 30px;
padding-bottom: 30px;
display: flex;
justify-content: center;
}
.wrapper {
--skew: 30deg;
width: 300px;
height: 300px;
border: 1px solid #ccc;
border-radius: 50%;
position: relative;
overflow: hidden;
}
.wrapper .sector {
position: absolute;
transform-origin: 100% 100%;
background: #ccc;
width: 5000px;
height: 5000px;
left: 50%;
top: 50%;
border: 1px solid #999;
margin-top: -5000px;
margin-left: -5000px;
}
.wrapper .sector:hover {
background: #000;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="wrapper">
<div class="sector" style="transform: rotate(0deg) skew(var(--skew));"></div>
<div class="sector" style="transform: rotate(60deg) skew(var(--skew));"></div>
<div class="sector" style="transform: rotate(120deg) skew(var(--skew));"></div>
<div class="sector" style="transform: rotate(180deg) skew(var(--skew));"></div>
<div class="sector" style="transform: rotate(240deg) skew(var(--skew));"></div>
<div class="sector" style="transform: rotate(300deg) skew(var(--skew));"></div>
</div>
</body>
</html>
It is possible to set the number of slices by calculating div tags and angles.
for 6 slices --skew:30deg;
And the interior angle of a circle is 360 degrees. If it's 6 pieces, divide by 6 to find the beginning of each slice. That means 0-60-120-180-240-300 values. If you are going to divide by 8, the values will come out accordingly and you should also revise the --skew value.
© 2022 - 2024 — McMap. All rights reserved.
<div>
elements (or whatever) that would be styled as short line segments, and then you'd rotate & translate them into a circle. It's just analytical geometry practice :-) Here is the MDN page about what transforms can do. – Definiens<canvas>
or SVG would be easier; you're going to have cross-browser issues no matter how you approach it, I suspect. – Definiens