Search code examples
csssvg

Partial circle with dashed line?


I'm trying to create a partial circle with dashed border but I can't find out how to achive that.

For instance, I want to create something like this using SVG

enter image description here

I know how to create both dashed border and a partial circle separately by using "stroke-dasharray". But I have no idea how to combine them.

For instance,

partial cicle

<svg viewBox="0 0 320 320">
  <path
    attr.stroke-dasharray="{{stroke_lenth}} {{circumference}}"
    d="M160 10
      a 150 150 0 0 1 0 300
      a 150 150 0 0 1 0 -300"
  />
</svg>

Solution

  • I would consider this previous answer that you can combine with a mask to hide a portion of the circle:

    svg {
      width:200px;
      transform:rotate(90deg); /* control the rotation here */
    }
    <svg viewBox="-3 -3 106 106">
      <defs>
        <mask id="m" >
          <rect x="-3" y="-2" width="100%" height="100%" fill="white"/>
          <!-- update the 120 below to increase/decrease the visible part-->
          <circle cx="50" cy="50" r="50" 
            stroke-dasharray="120, 1000"  
            fill="transparent" 
            stroke="black" 
            stroke-width="8"/>
         </mask>
      </defs>
      <!-- 
        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" mask="url(#m)" />
    </svg>

    A pure CSS solution but with low support actually due to the conic-gradient()

    .box {
      --d:4deg; /* distance between dashes */
      --n:30;   /* number of dashes */
      --c:#000; /* color of dashes */
      --b:2px;   /* control the thickness of border*/
      --m:60deg; /* the masked part */
      --r:0deg; /* rotation */
      
      width: 180px;
      display:inline-block;
      aspect-ratio: 1;
      border-radius:50%;
      transform:rotate(var(--r));
      background: 
        repeating-conic-gradient(
            var(--c)    0 calc(360deg/var(--n) - var(--d)), 
            transparent 0 calc(360deg/var(--n)));
      mask:
       conic-gradient(#000 var(--m),#0000 0) intersect,
       radial-gradient(farthest-side,#0000 calc(100% - var(--b) - 1px),#000 calc(100% - var(--b)) calc(100% - 1px),#0000);
    }
    
    
    
    body {
      background:linear-gradient(to right,yellow,pink);
    }
    <div class="box"></div>
    
    <div class="box" style="--n:20;--b:5px;width:150px;--c:blue;--m:20deg"></div>
    
    <div class="box" style="--n:8;--d:20deg;--b:10px;width:130px;--c:red;--m:180deg"></div>
    
    <div class="box" style="--n:18;--d:12deg;--b:8px;width:100px;--c:green;--r:90deg"></div>
    
    <div class="box" style="--n:10;--d:20deg;--b:3px;width:100px;--c:purple;--r:120deg;--m:120deg"></div>