44

I want to be able to draw a circle with a segment of it another colour, I would like the amount of a segment covered to be able to be increased in increments of 10% from 0% to 100%.

Any examples on Google are all sectors not segments.

Segments

So far this is the best I have been able to come up with:

div.outerClass {
    position: absolute;
    left: 10px;
    top: 10px;
    height: 2.5px;
    overflow: hidden;
    -ms-transform: rotate(270deg); /* IE 9 */
    -webkit-transform: rotate(270deg); /* Chrome, Safari, Opera */
    transform: rotate(270deg);
}

div.innerClass {
    width: 10px;
    height: 10px;
    border: 5px solid green;
    border-radius: 36px;
}
<div class="outerClass">
    <div class="innerClass"></div>
</div>

0%, 50% and 100% I can all do.

web-tiki
  • 99,765
  • 32
  • 217
  • 249
Greg
  • 754
  • 9
  • 18

4 Answers4

51

You can do it using linear-gradient

.circle{
  position:absolute;
  width:80px;
  height:80px;
  border-radius:50%;
  background: linear-gradient(
    to right,
    yellow  0%, yellow 10%,
    orange 10%, orange 20%,
    yellow 20%, yellow 30%,
    orange 30%, orange 40%,
    yellow 40%, yellow 50%,
    orange 50%, orange 60%,
    yellow 60%, yellow 70%,
    orange 70%, orange 80%,
    yellow 80%, yellow 90%,
    orange 90%, orange 100%
  );
}
<div class="circle"></div>

otherwise you can put 10 child elements inside your overflow:hidden circle parent:

.circle{
  position:absolute;
  width:80px;
  height:80px;
  border-radius:50%;
  overflow:hidden;
}
.circle > span{
  width:10%;
  height:100%;
  float:left;
}

.circle > span:nth-child(1){ background: yellow;}
.circle > span:nth-child(2){ background: orange;}
.circle > span:nth-child(3){ background: blue;}
.circle > span:nth-child(4){ background: green;}
.circle > span:nth-child(5){ background: fuchsia;}
.circle > span:nth-child(6){ background: orange;}
.circle > span:nth-child(7){ background: gold;}
.circle > span:nth-child(8){ background: tan;}
.circle > span:nth-child(9){ background: navy;}
.circle > span:nth-child(10){background: brown;}
<div class="circle">
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
</div>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • Thank you for the answer I thought about using gradients but I wasn't aware of linear gradients, unfortunately I have chosen Sergey's answer as it is simpler although both correctly answer my question. – Greg May 23 '15 at 13:33
  • 7
    @user2871826 Frankly I cannot see how sergey's answer is simpler. As you like. :) you're welcome – Roko C. Buljan May 23 '15 at 13:35
  • It is shorter in length and the system will be easier to implement with what I'm using it for. But yes there is not much difference in terms of simplicity. – Greg May 23 '15 at 13:37
  • 9
    This gradient uses one element as opposed to up to 11...seems simpler to me...and it can hold content properly too. – Paulie_D May 23 '15 at 13:42
  • I really like the first method, but it has the [unfortunate side effect of jaggy pixels on the edges on my screen](http://i.imgur.com/1R1Qhd0.png) (I'm using Chrome on a 15" MacBook Pro with Retina). – Cornstalks May 23 '15 at 17:01
  • @Cornstalks http://stackoverflow.com/questions/6492027/css-transform-jagged-edges-in-chrome – Roko C. Buljan May 23 '15 at 18:13
  • Use `linear-gradient` instead of `-webkit-linear-gradient` so other browser users could see the demo, too. – Salman A May 23 '15 at 18:54
  • @RokoC.Buljan: That helps, [but it's not perfect; there are still jaggies](http://i.imgur.com/Ourbikn.png). – Cornstalks May 23 '15 at 19:32
45

The cross-browser solution:

JSFiddle

.circle {
    border-radius: 50%;
    background: gray;
    width: 300px;
    height: 300px;
    overflow: hidden;
}
.segment {
    float: left;
    width: 10%;
    height: 100%;
}
    .segment_1 {
        background: red;
    }
    .segment_2 {
        background: green;
    }
    .segment_3 {
        background: yellow;
    }
    .segment_4 {
        background: blue;
    }
<div class="circle">
    <div class="segment segment_1"></div>
    <div class="segment segment_2"></div>
    <div class="segment segment_3"></div>
    <div class="segment segment_4"></div>
</div>
sergdenisov
  • 8,327
  • 9
  • 48
  • 63
  • 4
    @grgarside cause it changed only formatting style and I didn't like it. If SO has own style guide for posts/code, give me link please. – sergdenisov May 24 '15 at 14:39
  • 2
    @grgarside sorry, I didn't notice stack snippet. Did rollback and fixed formatting. – sergdenisov May 24 '15 at 14:51
  • 1
    @grgarside: In fairness, he didn't have to change the formatting style to make it work in a Stack Snippet either. Even if he used the Stack Snippet editor to generate the snippet, he could have just copied the code as is and it would work. There was no reason to have reformatted it, at all. – BoltClock May 24 '15 at 15:53
  • I converted the code to a stacksnippet, and clicked the tidy up button while at it. By the way the indentation looks odd to me. Can't see why you would indent `.segment_...` classes but not `.segment` itself. – Salman A May 24 '15 at 19:50
  • 2
    @SalmanA I like to format it this way. http://getbem.com/introduction/ — `.segment` is Block, `.segment_...` is Modifiers. – sergdenisov May 24 '15 at 20:01
  • @Falmarri if it's really important for you, I could explain in details. – sergdenisov May 25 '15 at 11:20
15

BOX SHADOW

Another approach could be using one element and box-shadows.

  • The main element is a circle (border-radius: 50%;) and has an aspect ratio of 1:1.

  • The pseudoelement is positioned left: -100%;, or just left of the main element.

  • 10 box shadows are applied to the pseudoelement, with different colour and different abscissae. I have put abscissae as 30px, as 30px is 10% of 300px ...

  • 10% of width was chosen because 10 stripes are needed.

div {
  height: 300px;
  width: 300px;
  border: 1px solid black;
  position: relative;
  border-radius: 50%;
  overflow: hidden;
}
div:before {
  position: absolute;
  content: '';
  height: inherit;
  width: inherit;
  left: -100%;
  background: red;
  box-shadow: 
    30px 0 0 chocolate,
    60px 0 0 hotpink,
    90px 0 0 indigo,
    120px 0 0 orangered,
    150px 0 0 gold,
    180px 0 0 deepskyblue,
    210px 0 0 springgreen,
    240px 0 0 darkslategray,
    270px 0 0 gold,
    300px 0 0 navy;
}
<div></div>
Max Payne
  • 2,423
  • 17
  • 32
  • 1
    I was literally surprised that there was no answer using box shadows! I thought someone wud already have posted it. I think you saw this question just now? I too started making a fiddle : https://jsfiddle.net/nqys0fyo/ :) – Max Payne May 24 '15 at 09:16
13

Another approach would be to use SVG. The segments are made with <rect /> elements and they are clipped to a circle using the <clipPath/> element :

svg{width:40%;display:block;margin:0 auto;}
use:hover{fill:#000;}
<svg viewBox="0 0 10 10">
  <defs>
    <clipPath id="circle">
      <circle cx="5" cy="5" r="5" />
    </clipPath>
    <rect id="seg" y="0" width="1" height="10" />
  </defs>  
  <g clip-path="url(#circle)">
    <use xlink:href="#seg" x="0" fill="pink"/>
    <use xlink:href="#seg" x="1" fill="green" />
    <use xlink:href="#seg" x="2" fill="orange" />
    <use xlink:href="#seg" x="3" fill="teal" />
    <use xlink:href="#seg" x="4" fill="tomato"/>
    <use xlink:href="#seg" x="5" fill="gold"/>
    <use xlink:href="#seg" x="6" fill="darkorange" />
    <use xlink:href="#seg" x="7" fill="pink" />
    <use xlink:href="#seg" x="8" fill="red" />
    <use xlink:href="#seg" x="9" fill="yellow" />
  </g>
</svg>
web-tiki
  • 99,765
  • 32
  • 217
  • 249
  • 1
    SVG rules! (if you're not worried about IE8) Nice example. We should really start/continue caring about SVG and show some more ♥ – Roko C. Buljan May 24 '15 at 18:26
  • 1
    Raphael with VML fall back will do for IE 6.0+ – Max Payne May 25 '15 at 02:07
  • 1
    @RokoC.Buljan yeah although this case can be quite easily handled with CSS I believe giving SVG more ♥ is a real benefit for everyone :) – web-tiki May 25 '15 at 08:52
  • in this case svg has no advantage over accepted answer. it has same no. of elements – Max Payne Jun 09 '15 at 12:41
  • @TimKrul it depends on what you need to do with the shape. If the number of HTML elements is the choise criteria then your answer is best. – web-tiki Jun 09 '15 at 12:44
  • @web-tiki i mean svg will not have advantage over accepted answer (html css) whatever would be needed to be done with svg could be done with simple html and css. like hover effect on different colours. single element one cant do that. – Max Payne Jun 09 '15 at 13:15