Aquí hay una versión optimizada de la conic-gradient()
solución donde puede controlar fácilmente la cantidad de guiones y el espacio entre
.box {
--d:4deg; /* distance between dashes */
--n:30; /* number of dashes */
--c:#000; /* color of dashes */
width: 180px;
display:inline-block;
border-radius:50%;
border:2px solid transparent; /* control the thickness of border*/
background:
linear-gradient(#fff,#fff) padding-box padding-box,
repeating-conic-gradient(
var(--c) 0 calc(360deg/var(--n) - var(--d)),
transparent 0 calc(360deg/var(--n))
) border-box;
}
/* keep the element square */
.box:before {
content:"";
display:block;
padding-top:100%;
}
<div class="box"></div>
<div class="box" style="--n:20;border-width:5px;width:150px"></div>
<div class="box" style="--n:8;--d:20deg;border-width:5px;width:150px"></div>
<div class="box" style="--n:10;--d:15deg;border-width:3px;width:100px"></div>
<div class="box" style="--n:10;--d:20deg;border-width:3px;width:100px"></div>
Para tener total transparencia consideramos mask
.box {
--d:4deg; /* distance between dashes */
--n:30; /* number of dashes */
--c:#000; /* color of dashes */
--b:2px; /* control the thickness of border*/
width: 180px;
display:inline-block;
border-radius:50%;
background:
repeating-conic-gradient(
var(--c) 0 calc(360deg/var(--n) - var(--d)),
transparent 0 calc(360deg/var(--n)));
-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--b)),#fff calc(100% - var(--b) + 1px));
mask:radial-gradient(farthest-side,transparent calc(100% - var(--b)),#fff calc(100% - var(--b) + 1px));
}
/* keep the element square */
.box:before {
content:"";
display:block;
padding-top:100%;
}
body {
background:linear-gradient(to right,yellow,pink);
}
<div class="box"></div>
<div class="box" style="--n:20;--b:5px;width:150px;--c:blue"></div>
<div class="box" style="--n:8;--d:20deg;--b:10px;width:130px;--c:red"></div>
<div class="box" style="--n:18;--d:12deg;--b:8px;width:100px;--c:green"></div>
<div class="box" style="--n:10;--d:20deg;--b:3px;width:100px;--c:purple"></div>
Para hacer las cosas divertidas , incluso podemos considerar una coloración más compleja en los guiones:
.box {
--d:4deg; /* distance between dashes */
--n:30; /* number of dashes */
--b:2px; /* control the thickness of border*/
width: 180px;
display:inline-block;
border-radius:50%;
background:linear-gradient(red,blue);
-webkit-mask:
radial-gradient(farthest-side,transparent calc(100% - var(--b)),#fff calc(100% - var(--b) + 1px)),
repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--d)),transparent 0 calc(360deg/var(--n)));
-webkit-mask-composite: source-in;
mask:
radial-gradient(farthest-side,transparent calc(100% - var(--b)),#fff calc(100% - var(--b) + 1px)),
repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--d)),transparent 0 calc(360deg/var(--n)));
mask-composite: intersect;
}
/* keep the element square */
.box:before {
content:"";
display:block;
padding-top:100%;
}
body {
background:linear-gradient(to right,yellow,pink);
}
<div class="box"></div>
<div class="box" style="--n:20;--b:5px;width:150px;background:conic-gradient(green,orange,black)"></div>
<div class="box" style="--n:8;--d:20deg;--b:10px;width:130px;background:conic-gradient(black,white,black)"></div>
<div class="box" style="--n:18;--d:12deg;--b:8px;width:100px;background:linear-gradient(60deg,red 50%,green 0)"></div>
<div class="box" style="--n:10;--d:20deg;--b:3px;width:100px;background:#fff"></div>
Seguramente querrás algo de contenido dentro, así que mejor aplica la máscara / fondo en un pseudo elemento para evitar enmascarar el contenido:
.box {
--d:4deg; /* distance between dashes */
--n:30; /* number of dashes */
--b:2px; /* control the thickness of border*/
width: 180px;
display:inline-flex;
justify-content:center;
align-items:center;
font-size:35px;
border-radius:50%;
position:relative;
}
.box::after {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
z-index:-1;
border-radius:inherit;
background:var(--c,linear-gradient(red,blue));
-webkit-mask:
radial-gradient(farthest-side,transparent calc(100% - var(--b)),#fff calc(100% - var(--b) + 1px)),
repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--d)),transparent 0 calc(360deg/var(--n)));
-webkit-mask-composite: source-in;
mask:
radial-gradient(farthest-side,transparent calc(100% - var(--b)),#fff calc(100% - var(--b) + 1px)),
repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--d)),transparent 0 calc(360deg/var(--n)));
mask-composite: intersect;
}
/* keep the element square */
.box:before {
content:"";
padding-top:100%;
}
body {
background:linear-gradient(to right,yellow,pink);
}
<div class="box">19</div>
<div class="box" style="--n:20;--b:5px;width:150px;--c:conic-gradient(green,orange,black)">17</div>
<div class="box" style="--n:8;--d:20deg;--b:10px;width:130px;--c:conic-gradient(black,white,black)">5</div>
<div class="box" style="--n:18;--d:12deg;--b:8px;width:100px;--c:linear-gradient(60deg,red 50%,green 0)">9</div>
<div class="box" style="--n:10;--d:20deg;--b:3px;width:100px;--c:#fff">13</div>
Pregunta relacionada para obtener más ideas de CSS para lograr un resultado similar: Gráfico de sectores de CSS solamente: ¿cómo agregar espaciado / relleno entre sectores? . Encontrará más formas compatibles que conic-gradient()
(en realidad no funciona en Firefox), pero debe usar mucho código, a diferencia de la solución anterior, donde solo se necesita un elemento.
Usando SVG también necesitará algunos cálculos para asegurarse de tener un espaciado uniforme:
svg {
width:200px;
}
<svg viewBox="-3 -3 106 106">
<!--
The circumference of the circle is 2*PI*R ~ 314.16
if we want N dashed we use d=314.16/N
For N = 20 we have d=15.71
For a gap of 5 we will have "10.71,5" (d - gap,gap)
-->
<circle cx="50" cy="50" r="50"
stroke-dasharray="10.71, 5"
fill="transparent"
stroke="black"
stroke-width="5" />
</svg>
Con las variables CSS podemos facilitarlo, pero no es compatible con todos los navegadores (en realidad no funciona en Firefox)
svg {
--n:20; /* number of dashes*/
--d:5; /* distance */
width:200px;
}
svg circle {
stroke-dasharray:calc((2*3.14*50)/var(--n) - var(--d)), var(--d);
}
<svg viewBox="-3 -3 106 106">
<circle cx="50" cy="50" r="50" fill="transparent" stroke="black" stroke-width="5" />
</svg>
<svg viewBox="-3 -3 106 106" style="width:150px;--n:20;--d:10">
<circle cx="50" cy="50" r="50" fill="transparent" stroke="red" stroke-width="5" />
</svg>
<svg viewBox="-3 -3 106 106" style="width:100px;--n:8;--d:15">
<circle cx="50" cy="50" r="50" fill="transparent" stroke="green" stroke-width="5" />
</svg>
También podemos usar fácilmente el SVG como fondo para hacer las cosas más flexibles:
.box {
display:inline-block;
width:200px;
background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-3 -3 106 106"><circle cx="50" cy="50" r="50" fill="transparent" stroke="black" stroke-width="5" style="stroke-dasharray:29.25, 10" /></svg>') center/contain;
}
.box:before {
content:"";
display:block;
padding-top:100%;
}
<div class="box">
</div>
<div class="box" style="width:150px;">
</div>
<div class="box" style="width:100px;">
</div>
Cuando se usa como fondo, debe establecer manualmente el valor para que necesite un fondo diferente cada vez. Solo podemos hacer que el color sea fácil de cambiar usando SVG como máscara;
.box {
display:inline-block;
width:200px;
position:relative;
}
.box:before {
content:"";
display:block;
padding-top:100%;
}
.box::after {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
z-index:-1;
background:var(--c,red);
-webkit-mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-3 -3 106 106"><circle cx="50" cy="50" r="50" fill="transparent" stroke="black" stroke-width="5" style="stroke-dasharray:29.25, 10" /></svg>') center/contain;
mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-3 -3 106 106"><circle cx="50" cy="50" r="50" fill="transparent" stroke="black" stroke-width="5" style="stroke-dasharray:29.25, 10" /></svg>') center/contain;
}
<div class="box">
</div>
<div class="box" style="width:150px;--c:linear-gradient(60deg,green 50%,yellow 0);">
</div>
<div class="box" style="width:100px;--c:linear-gradient(red,blue)">
</div>