Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to draw a partial circle outline in CSS (open ring shape)?

I'm interested in creating a loading spinner entirely in CSS but in order to do so I would need to be able to draw a open ring shape like this:

enter image description here

The ring would draw itself around the circumference of the circle. Is this achievable in CSS?

like image 993
colindunn Avatar asked Feb 14 '17 19:02

colindunn


People also ask

How do you make a half circle border in CSS?

You could use border-top-left-radius and border-top-right-radius properties to round the corners on the box according to the box's height (and added borders). Then add a border to top/right/left sides of the box to achieve the effect.

How do you make a hollow circle in CSS?

Creating an empty circle with CSS To create an empty circle first of all add an empty <div> element. Use CSS border-radius: 50% to make the div element circular. Additionally set the height, width and border of <div> element.


2 Answers

To create a circle that gradually draws it's outer path, use SVG.

SVG's stroke-dasharray property will turn any path into a dashed line, which you can use to your advantage by setting the dash size to be almost as long as the path itself.

Then use a CSS animation to gradually change the stroke-dashoffset to move the dash around the perimeter of your circle.

circle {    fill: white;    stroke: black;    stroke-width: 2;    stroke-dasharray: 250;    stroke-dashoffset: 1000;    animation: rotate 5s linear infinite;  }    @keyframes rotate {    to {      stroke-dashoffset: 0;    }  }
<svg height="100" width="100">    <circle cx="50" cy="50" r="40" />  </svg>
like image 180
Dylan Stark Avatar answered Sep 19 '22 15:09

Dylan Stark


Static Image

A simplified example that just relies on a single HTML element and CSS class might look like this :

.arc {   /* Border size and color */   border: 2px solid #000;   /* Creates a circle */   border-radius: 50%;   /* Circle size */   height: 100px;   width: 100px;   /* Use transparent borders to define opening (more transparent = larger opening) */   border-top-color: transparent;   border-left-color: transparent;   /* Use transform to rotate to adjust where opening appears */   transform: rotate(300deg) } 

Example

enter image description here

.arc {   border: 2px solid #000;   border-radius: 50%;   height: 100px;   width: 100px;   border-top-color: transparent;   transform: rotate(300deg) }
<div class='arc'></div>

Rotating Image

You can apply a basic rotation to the previous static example by taking advantage of CSS-based animations using @keyframes :

.arc {   /* Border size and color */   border: 2px solid #000;   /* Creates a circle */   border-radius: 50%;   /* Circle size */   height: 100px;   width: 100px;   /* Use transparent borders to define opening (more transparent = larger opening) */   border-top-color: transparent;   /* Rotate indefinitely (longer time = slower rotation) */   animation: rotate 2s infinite linear; }  @keyframes rotate {   0%    { transform: rotate(0deg);  }   100%  { transform: rotate(360deg);  } } 

Example

enter image description here

.arc {   border: 2px solid #000;   border-radius: 50%;   height: 100px;   width: 100px;   border-top-color: transparent;   animation: rotate 2s infinite linear; }  @keyframes rotate {   0%    { transform: rotate(0deg);  }   100%  { transform: rotate(360deg);  } }
<div class='arc'></div>

Drawing (without SVG)

Another approach that I came across, while not nearly as elegant as the previous approaches does appear to achieve your desired effect. In involves the use of several animations as well as showing/hiding different sections of the circle as necessary.

The code snippet contains an example demonstrating it.

Example

enter image description here

#container {   position: absolute;   width: 100px;   height: 100px;   animation: colors 1s infinite; } #halfclip {   width: 50%;   height: 100%;   right: 0px;   position: absolute;   overflow: hidden;   transform-origin: left center;   animation: cliprotate 4s steps(2) infinite;   -webkit-animation: cliprotate 4s steps(2) infinite; } .halfcircle {   box-sizing: border-box;   height: 100%;   right: 0px;   position: absolute;   border: solid 2px transparent;   border-top-color: #000;   border-left-color: #000;   border-radius: 50%; } #clipped {   width: 200%;   animation: rotate 2s linear infinite;   -webkit-animation: rotate 2s linear infinite; } #fixed {   width: 100%;   transform: rotate(135deg);   animation: showfixed 4s steps(2) infinite;   -webkit-animation: showfixed 4s linear infinite; } @-webkit-keyframes cliprotate {   0% {     transform: rotate(0deg);   }   100% {     transform: rotate(360deg);   } } @keyframes cliprotate {   0% {     transform: rotate(0deg);   }   100% {     transform: rotate(360deg);   } } @-webkit-keyframes rotate {   0% {     transform: rotate(-45deg);   }   100% {     transform: rotate(135deg);   } } @keyframes rotate {   0% {     transform: rotate(-45deg);   }   100% {     transform: rotate(135deg);   } } @-webkit-keyframes showfixed {   0% {     opacity: 0;   }   49.9% {     opacity: 0;   }   50% {     opacity: 1;   }   100% {     opacity: 1;   } }
<div id="container">   <div id="halfclip">     <div class="halfcircle" id="clipped">     </div>   </div>   <div class="halfcircle" id="fixed">   </div> </div>

Drawing (with SVG)

Taking advantage of SVG is probably the best way to address this problem, as it's explicitly designed to handle drawing within the browser. I'd highly recommend that approach if SVG support is available.

Dylan's response details what this implementation might look like.

like image 33
Rion Williams Avatar answered Sep 18 '22 15:09

Rion Williams