<main>
<article class="row">
<h1>Radial Progress Bars</h1>
</article>
<div class="arrow down"></div>
<section class="row">
<svg class="radial-progress" data-percentage="82" viewBox="0 0 80 80">
<circle class="incomplete" cx="40" cy="40" r="35"></circle>
<circle class="complete" cx="40" cy="40" r="35" style="stroke-dashoffset: 39.58406743523136;"></circle>
<text class="percentage" x="50%" y="57%" transform="matrix(0, 1, -1, 0, 80, 0)">82%</text>
</svg>
<svg class="radial-progress" data-percentage="33" viewBox="0 0 80 80">
<circle class="incomplete" cx="40" cy="40" r="35"></circle>
<circle class="complete" cx="40" cy="40" r="35" style="stroke-dashoffset: 147.3406954533613;"></circle>
<text class="percentage" x="50%" y="57%" transform="matrix(0, 1, -1, 0, 80, 0)">33%</text>
</svg>
<svg class="radial-progress" data-percentage="71" viewBox="0 0 80 80">
<circle class="incomplete" cx="40" cy="40" r="35"></circle>
<circle class="complete" cx="40" cy="40" r="35" style="stroke-dashoffset: 63.774330867872806;"></circle>
<text class="percentage" x="50%" y="57%" transform="matrix(0, 1, -1, 0, 80, 0)">71%</text>
</svg>
<svg class="radial-progress" data-percentage="24" viewBox="0 0 80 80">
<circle class="incomplete" cx="40" cy="40" r="35"></circle>
<circle class="complete" cx="40" cy="40" r="35" style="stroke-dashoffset: 167.13272917097697;"></circle>
<text class="percentage" x="50%" y="57%" transform="matrix(0, 1, -1, 0, 80, 0)">24%</text>
</svg>
<svg class="radial-progress" data-percentage="100" viewBox="0 0 80 80">
<circle class="incomplete" cx="40" cy="40" r="35"></circle>
<circle class="complete" cx="40" cy="40" r="35" style="stroke-dashoffset: 0;"></circle>
<text class="percentage" x="50%" y="57%" transform="matrix(0, 1, -1, 0, 80, 0)">100%</text>
</svg>
<svg class="radial-progress" data-percentage="0" viewBox="0 0 80 80">
<circle class="incomplete" cx="40" cy="40" r="35"></circle>
<circle class="complete" cx="40" cy="40" r="35" style="stroke-dashoffset: 219.91148575129;"></circle>
<text class="percentage" x="50%" y="57%" transform="matrix(0, 1, -1, 0, 80, 0)">0%</text>
</svg>
</section>
<div class="arrow up"></div>
<article class="row">
<p>The radial progress bars are driven by the <code>data-percentage</code> in each <code>svg</code>, and the radius (<code>r</code>) of its child <code>circle.complete</code>. The percentage is then calculated into the overall circumference (2πr) of the circle, and then spits out the value in <code>stroke-dashoffset</code>.</p>
<p>Each infographic will individually animate on scroll. The animation begins once the svg is approximately 25% into the window.</p>
<p>For a no JavaScript option, the <code>stroke-dashoffset</code> is manually inline-styled for each <code>circle.complete</code>. The JavaScript removes the inline styling, automatically calculates the value, and then spits it back out in a smooth transition.</p>
</article>
</main>
@import url(https://fonts.googleapis.com/css?family=Oswald:400|Raleway:400,700,400italic,700italic);
*,
:before,
:after {
box-sizing: border-box;
}
body {
background-color: #1d1f20;
color: #e5e5e5;
font: 16px/1.25 'Raleway', sans-serif;
margin: 0;
}
.row {
margin-left: auto;
margin-right: auto;
max-width: 80em;
padding: 1em;
}
section {
text-align: center;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: 'Oswald', sans-serif;
font-weight: 400;
text-align: center;
}
p {
margin-left: auto;
margin-right: auto;
max-width: 36em;
}
code {
color: #f1e399;
font-style: italic;
}
.arrow {
border: 2em solid transparent;
height: 0;
margin: 50vh auto;
width: 0;
}
.arrow.down {
border-bottom: none;
border-top-color: #e5e5e5;
}
.arrow.up {
border-bottom-color: #e5e5e5;
border-top: none;
}
/*** RADIAL PROGRESS ***/
/* Circumference = 2πr */
/* π = 3.1415926535898 */
/* r = 35 */
svg.radial-progress {
height: auto;
max-width: 200px;
padding: 1em;
transform: rotate(-90deg);
width: 100%;
}
svg.radial-progress circle {
fill: rgba(0,0,0,0);
stroke: #fff;
stroke-dashoffset: 219.91148575129; /* Circumference */
stroke-width: 10;
}
svg.radial-progress circle.incomplete {
opacity: 0.25;
}
svg.radial-progress circle.complete {
stroke-dasharray: 219.91148575129; /* Circumference */
}
svg.radial-progress text {
fill: #fff;
font: 400 1em/1 'Oswald', sans-serif;
text-anchor: middle;
}
/*** COLORS ***/
/* Primary */
svg.radial-progress:nth-of-type(6n+1) circle {
stroke: #a2ed56;
}
/* Secondary */
svg.radial-progress:nth-of-type(6n+2) circle {
stroke: #83e4e2;
}
/* Tertiary */
svg.radial-progress:nth-of-type(6n+3) circle {
stroke: #fd6470;
}
/* Quaternary */
svg.radial-progress:nth-of-type(6n+4) circle {
stroke: #fca858;
}
/* Quinary */
svg.radial-progress:nth-of-type(6n+5) circle {
stroke: #fddc32;
}
$(function(){
// Remove svg.radial-progress .complete inline styling
$('svg.radial-progress').each(function( index, value ) {
$(this).find($('circle.complete')).removeAttr( 'style' );
});
// Activate progress animation on scroll
$(window).scroll(function(){
$('svg.radial-progress').each(function( index, value ) {
// If svg.radial-progress is approximately 25% vertically into the window when scrolling from the top or the bottom
if (
$(window).scrollTop() > $(this).offset().top - ($(window).height() * 0.75) &&
$(window).scrollTop() < $(this).offset().top + $(this).height() - ($(window).height() * 0.25)
) {
// Get percentage of progress
percent = $(value).data('percentage');
// Get radius of the svg's circle.complete
radius = $(this).find($('circle.complete')).attr('r');
// Get circumference (2πr)
circumference = 2 * Math.PI * radius;
// Get stroke-dashoffset value based on the percentage of the circumference
strokeDashOffset = circumference - ((percent * circumference) / 100);
// Transition progress for 1.25 seconds
$(this).find($('circle.complete')).animate({'stroke-dashoffset': strokeDashOffset}, 1250);
}
});
}).trigger('scroll');
});
This Pen doesn't use any external CSS resources.