Segments in a circle using CSS
Asked Answered
D

5

35

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?

enter image description here

Decarbonate answered 6/1, 2013 at 17:3 Comment(6)
You could do it with little elements and CSS rotation transformations, but that seems pretty painful.Definiens
Mr. Pointy please tell me how...I really want to know! :) Pwetty please with sugar lumps on top! :)Decarbonate
Well I'm not a CSS transform expert, but you'd basically make <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
Oh wait - are you asking about how to draw radial line segments inside the circle? If so, I completely misunderstood; I thought you were trying to draw the circle itself.Definiens
Yes, segments inside the circle. That is what I wanted. Was my diagram misleading? I want each segment to highlight when hovered over too.Decarbonate
That might be possible, but it's probably pretty tricky. Possibly using a <canvas> or SVG would be easier; you're going to have cross-browser issues no matter how you approach it, I suspect.Definiens
F
60

Yes, you can get such slices of custom angles using either one of the following two methods:

  1. 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.
  2. 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>
Faires answered 6/1, 2013 at 19:25 Comment(2)
the circular menu disappeared :(Carvey
@Carvey probably a similar dabblet showing how the idea works dabblet.com/gist/5020696 ... probably late comment, but did not see it before now ;) could be looking like citrus too codepen.io/gcyrillus/pen/wutEKDespairing
E
8

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

Ernst answered 6/1, 2013 at 17:35 Comment(0)
L
8

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>
Lissome answered 20/1, 2019 at 2:7 Comment(1)
This seems to repeat Ana's answer from 6 years prior.Pipsqueak
B
4

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>
Bowling answered 29/10, 2020 at 13:18 Comment(0)
H
-1

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.

Headliner answered 6/9, 2023 at 21:59 Comment(1)
This repeats the solution from the top answer from 2013. And at least one other one.Pipsqueak

© 2022 - 2024 — McMap. All rights reserved.