How to make a doughnut segment using only CSS

前端 未结 2 1053
天涯浪人
天涯浪人 2020-12-19 11:42

How to make this shape use only css

\"doughnut

What I have tried:

相关标签:
2条回答
  • 2020-12-19 11:54

    In case you prefer your border method more than SVG or gradients, here is an approach using just border-radius, the pseudo element ::after and some positioning:

    .shape,
    .shape::after {
      position: absolute;
      border-radius: 100%;
    }
    
    .shape {
      height: 200px;
      width: 200px;
      border: 100px solid transparent;
      border-top: 100px solid #375c89;
    }
    
    .shape::after {
      content: '';
      height: 190px;
      width: 198px;
      top: -95px;
      left: -89px;
      border: 90px solid transparent;
      border-top: 90px solid #4f81bc;
    }
    <div class="shape"></div>

    How it works

    You can create this shape in two steps.

    Step 1: Create a doughnut segment using border-radius: 100% to give it a circle like shape. Then apply a color only to the top border and make the other borders transparent. This way you get a circle segment. Now give your element a width and a height greater than 0 to transform the circle into a doughnut.

    Step 2: Apply the same styles to the pseudo element ::after but giving it a slightly less width,height and border width. Adjust the values for your needs. Now position both elements with position: absolute to adjust the position of the overlapping pseudo element to center it properly over the main element.

    The good

    • Better browser compatibility especially for older browsers than gradients, clip-path or SVG.
    • The angle of the circular shape can simply be adjusted with height and width

    The bad

    • As the other parts of the border are still there (transparent) you need to adjust the size of the parent element according to the shape and set overflow: hidden;
    • for changing the border width of the shape, you need to reposition the ::after element

    You can as well use both pseudo elements ::before and ::after to create the shape and easily adjust the position with sizing and margin (thanks to Temani for pointing this out in the comments):

    .shape {
      position: relative;
      width: 400px;
      height: 400px;
    }
    
    .shape::before,
    .shape::after {
      content: '';
      position: absolute;
      border-radius: 100%;
      right: 0;
      left: 0;
      bottom: 0;
      top: 0;
    }
    
    .shape:before {
      border: 100px solid transparent;
      border-top-color: #375c89;
    }
    
    .shape::after {
      margin: 5px 12px;
      border: 90px solid transparent;
      border-top-color: #4f81bc;
      height: 45%;
    }
    <div class="shape"></div>

    0 讨论(0)
  • 2020-12-19 12:03

    I would go with some linear/radial-gradient like this:

    .box {
      width:200px;
      height:200px;
      border-radius:50%;
      background:
       linear-gradient(-30deg, white 50%,transparent 50.5%),
       linear-gradient(30deg,  white 50%,transparent 50.5%),
       radial-gradient(farthest-side at center,transparent 40%,blue 41%);
    }
    <div class="box">
    
    </div>

    And with border:

    .box {
      width:200px;
      height:200px;
      border-radius:50%;
      background:
       linear-gradient(to top,white 58.5%,transparent 60%),
       linear-gradient(-30deg, white calc(50% - 4px),green calc(50% - 4px) 50%,transparent 0),
       linear-gradient(30deg,  white calc(50% - 4px),green calc(50% - 4px) 50%,transparent 0),
       radial-gradient(farthest-side at center,
        transparent calc(42% - 5px),
        green calc(42% - 4px) 42%,
        blue 42% calc(100% - 4px),green calc(100% - 3px));
    }
    <div class="box">
    
    </div>

    You can also consider SVG which can be easier:

    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64' width='300' height='300' fill='blue'>
      <path stroke="green" stroke-width=1 d='M24 32 C28 28 37 28 40 32 L52 22 C38 8 26 8 12 22 Z' />
    </svg>

    Here is another Idea with clip-path:

    .box {
      width:200px;
      height:200px;
      border-radius:50%;
      background:
      radial-gradient(farthest-side at center,transparent 40%,blue 41%);
      clip-path: polygon(0 0,0 10%, 50% 50%, 100% 10%,100% 0);
    }
    <div class="box">
    
    </div>

    Related question: CSS Only Pie Chart - How to add spacing/padding between slices?

    0 讨论(0)
提交回复
热议问题