Je suis intéressé par la création d'une filière de chargement entièrement en CSS, mais pour ce faire, je devrais pouvoir dessiner une forme d'anneau ouvert comme ceci:
L'anneau se dessinerait autour de la circonférence du cercle. Est-ce réalisable en CSS?
Pour créer un cercle qui dessine progressivement son chemin extérieur, utilisez SVG.
La propriété stroke-dasharray
De SVG transformera n'importe quel chemin en une ligne pointillée, que vous pouvez utiliser à votre avantage en définissant la taille du tiret comme étant presque aussi longue que le chemin lui-même.
Utilisez ensuite une animation CSS pour modifier progressivement le stroke-dashoffset
Pour déplacer le tiret sur le périmètre de votre cercle.
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>
Un exemple simplifié qui repose uniquement sur un seul élément HTML et une classe CSS pourrait ressembler à ceci:
.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)
}
Exemple
.arc {
border: 2px solid #000;
border-radius: 50%;
height: 100px;
width: 100px;
border-top-color: transparent;
transform: rotate(300deg)
}
<div class='arc'></div>
Vous pouvez appliquer une rotation de base à l'exemple statique précédent en tirant parti des animations CSS à l'aide de @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); }
}
Exemple
.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>
Une autre approche que j'ai rencontrée , bien qu'elle ne soit pas aussi élégante que les approches précédentes semble obtenir l'effet souhaité. En implique l'utilisation de plusieurs animations ainsi que l'affichage/masquage des différentes sections du cercle si nécessaire.
L'extrait de code contient un exemple le démontrant.
Exemple
#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>
Profiter de SVG est probablement le meilleur moyen de résoudre ce problème, car il est explicitement conçu pour gérer le dessin dans le navigateur. Je recommanderais fortement cette approche si le support SVG est disponible.
réponse de Dylan détaille à quoi pourrait ressembler cette implémentation.
Vous pouvez simplement prendre un pseudo-élément ::after
pour créer la partie ouverte, avec juste chevauchement de l'élément cercle. L'avantage est que la partie ouverte peut être aussi longue que souhaité (non limitée à un cercle complet 3/4).
.circle {
width: 100px;
height: 100px;
border: 2px solid;
border-radius: 50%;
margin: 30px;
animation: rotate 1s infinite linear;
}
.circle::after {
content: "";
display: block;
width: 80px;
height: 80px;
background: white;
border-radius: 50%;
margin: -30% 0 0 -30%;
}
@keyframes rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
<div class="circle"></div>
pour la pseudo version, vous pouvez également utiliser linear-gradient
(l'ombre peut être diminuée ou augmentée) et background-clip
,
où il est disponible, mix-blend-mode
peut le rendre translucide,
currentcolor
et animation
peuvent également être utilisés pour animer la couleur:
.loader {
font-size: 1.5em;
color: gray;
position: relative;
padding: 3px;
/* make a square */
height: 100px;
width: 100px;
/* center content*/
display: flex;
align-items: center;
justify-content: center;
animation: coloranim infinite 5s;
}
.circle {
border-radius: 100%;
overflow: hidden;
}
.loader:after {
border-radius: inherit;
color: inherit;
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 3px;
background: linear-gradient(white, white), linear-gradient(0deg, transparent 40%, currentcolor 60%), linear-gradient(50deg, transparent 50%, currentcolor 52%);
background-clip: content-box, border-box, border-box;
z-index: -1;
mix-blend-mode: multiply;/* if avalaible, else bg remains white */
}
.spin:after {
animation: spin 2s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
@keyframes coloranim {
20% {
color: tomato;
}
40% {
color: purple;
}
60% {
color: turquoise;
}
80% {
color: green;
}
}
/* demo purpose, use your own style wherever your loader is needed */
html {
height: 100%;
display: flex;
background: url(http://lorempixel.com/800/800/food/3);
background-size: cover;
box-shadow: inset 0 0 0 2000px rgba(255, 255, 255, 0.3)
}
body {
margin: auto;
}
<div class="spin circle loader coloranim"> loading... </div>