cssdonut-chart

CSS3 simple donut chart


What I'm trying to do is create a simple donut chart. I'm currently using CSS(3) only but I don't know if it's possible without javascript.

What I have so far: http://jsfiddle.net/aBP5Q/

HTML:

<div class="donut-container" style="background: #9C0;">
    <div class="donut-inner">
        <div class="donut-label">HTML</div>
    </div>
</div>

CSS:

.donut-container {
    width: 150px;
    height: 150px;
    float: left;
    -webkit-border-radius: 75px;
    -moz-border-radius: 75px;
    border-radius: 75px;
    margin-right: 20px;
}

.donut-inner {
    width: 134px;
    height: 134px;
    position: relative;
    top: 8px;
    left: 8px;
    background: #FFF;
    -webkit-border-radius: 65px;
    -moz-border-radius: 65px;
    border-radius: 65px;
}

.donut-label {
    line-height: 130px;
    text-align: center;
    font-size: 20px;
}

I would like to display the green and blue colors as the precentage. So no green is 0% and full green (360 degrees) is 100%. Maybe even with a simple animation when the chart is loaded if its possible.

Your help is much appreciated.


Solution

  • SVG for the win!

    .item {
        position: relative;
        float: left;
    }
    
    .item h2 {
        text-align:center;
        position: absolute;
        line-height: 125px;
        width: 100%;
    }
    
    svg {
       -webkit-transform: rotate(-90deg);
        transform: rotate(-90deg);
    }
    
    .circle_animation {
      stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
      stroke-dashoffset: 440;
    }
    
    .html .circle_animation {
        -webkit-animation: html 1s ease-out forwards;
        animation: html 1s ease-out forwards;
    }
    
    .css .circle_animation {
        -webkit-animation: css 1s ease-out forwards;
        animation: css 1s ease-out forwards;
    }
    
    @-webkit-keyframes html {
      to {
        stroke-dashoffset: 80; /* 50% would be 220 (half the initial value specified above) */
      }
    }
    
    @keyframes html {
      to {
        stroke-dashoffset: 80;
      }
    }
    
    @-webkit-keyframes css {
      to {
        stroke-dashoffset: 160;
      }
    }
    
    @keyframes css {
      to {
        stroke-dashoffset: 160;
      }
    }
    <div class="item html">
        <h2>HTML</h2>
        <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
         <g>
          <title>Layer 1</title>
          <circle class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#6fdb6f" fill="none"/>
         </g>
        </svg>
    </div>
    
    <div class="item css">
        <h2>CSS</h2>
        <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
         <g>
          <title>Layer 1</title>
          <circle class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#69aff4" fill="none"/>
         </g>
        </svg>
    </div>

    JSFiddle version


    Here is a version with background circles as requested in the comments:

    .item {
        position: relative;
        float: left;
    }
    
    .item h2 {
        text-align:center;
        position: absolute;
        line-height: 125px;
        width: 100%;
    }
    
    svg {
       -webkit-transform: rotate(-90deg);
        transform: rotate(-90deg);
    }
    
    .circle_animation {
      stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
      stroke-dashoffset: 440;
    }
    
    .html .circle_animation {
        -webkit-animation: html 1s ease-out forwards;
        animation: html 1s ease-out forwards;
    }
    
    .css .circle_animation {
        -webkit-animation: css 1s ease-out forwards;
        animation: css 1s ease-out forwards;
    }
    
    @-webkit-keyframes html {
      to {
        stroke-dashoffset: 80; /* 50% would be 220 (half the initial value specified above) */
      }
    }
    
    @keyframes html {
      to {
        stroke-dashoffset: 80;
      }
    }
    
    @-webkit-keyframes css {
      to {
        stroke-dashoffset: 160;
      }
    }
    
    @keyframes css {
      to {
        stroke-dashoffset: 160;
      }
    }
    <div class="item html">
        <h2>HTML</h2>
        <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
         <g>
          <title>Layer 1</title>
          <circle r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#f2f2f2" fill="none"/>
          <circle class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#6fdb6f" fill="none"/>
         </g>
        </svg>
    </div>
    
    <div class="item css">
        <h2>CSS</h2>
        <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
         <g>
          <title>Layer 1</title>
          <circle r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#f2f2f2" fill="none"/>
          <circle class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#69aff4" fill="none"/>
         </g>
        </svg>
    </div>


    How does it work?

    stroke-dasharray is used to define the 'pattern' a dashed line uses (MDN). By providing a single value you create a pattern with a dash of 440px and a space of 440px. (440px is roughly the circumference of the circle).

    stroke-dashoffset effectively moves the starting point of the dash pattern (MDN).

    A dash-offset of 220 (half of the stroke-dasharray) would produce a half-circle. 110 = quarter circle etc.