仅使用 css 的百分比饼图 [英] Percent pie chart with css only
问题描述
我发现了非常漂亮的百分比饼图",并且只想用 CSS 创建它.不需要动画.只是静态的图片".
我明白如果我想创建这种图表,我需要使用这些元素
问题是
- 如何创建元素#2?
- 如何为更小 (5%) 或更高百分比 (80%) 的值管理元素 #2 的形状?
New answer 2021
通过一些现代技术,我们可以改进代码.您可以有圆角边缘,也可以考虑动画:
@property --p{语法:'<数字>';继承:真实;初始值:1;}.pie {--p:20;/* 百分比 */--b:22px;/* 厚度 */--c:深红色;/* 颜色 */--w:150px;/* 规模*/宽度:变量(--w);纵横比:1/1;位置:相对;显示:内联网格;边距:5px;地点内容:中心;字体大小:25px;字体粗细:粗体;字体系列:无衬线;}.pie:之前,.pie:在{之后内容:"";位置:绝对;边界半径:50%;}.pie:之前{插图:0;背景:径向梯度(最远侧,var(--c)98%,#0000)顶部/var(--b)var(--b)无重复,圆锥梯度(var(--c) calc(var(--p)*1%),#0000 0);-webkit-mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));掩码:径向梯度(最远边,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));}.pie:在{之后插图:计算(50% - var(--b)/2);背景:var(--c);变换:旋转(calc(var(--p)*3.6deg - 90deg))translate(calc(var(--w)/2 - 50%));}.animate {动画:p 1s .5s 两者;}.no-round:before {背景尺寸:0 0,自动;}.no-round:after {内容:无;}@关键帧p{来自{--p:0;}}身体 {背景:#ddd;}
20%/div<div class="pie" style="--p:40;--c:darkblue;--b:10px">40%/div<div class="pie no-round" style="--p:60;--c:purple;--b:15px">60%/div<div class="pie animate" style="--p:80;--c:orange;">80%/div<div class="pie animate no-round" style="--p:90;--c:lightgreen">90%
旧答案
您可以使用多个背景来执行此操作.
从0%
到50%
:
.box {宽度:100px;高度:100px;显示:内联块;边界半径:50%;填充:5px;背景:线性梯度(#ccc,#ccc)内容框,线性梯度(var(--v),#f2f2f2 50%,透明0),线性渐变(向右,#f2f2f2 50%,蓝色 0);}
<div class="box" style="--v:-90deg"></div><!-- 0% --><div class="box" style="--v:-45deg"></div><!-- 12.5% --><div class="box" style="--v: 0deg"></div><!-- 25% --><div class="box" style="--v: 45deg"></div><!-- 37.5% --><div class="box" style="--v: 90deg"></div><!-- 50% --><p>公式为[p=(18/5)*x-90].<small>其中 x 是百分比,p 是度数</small></p><p>对于 x = 5% -->p = -72deg </p><div class="box" style="--v:-72deg"></div>
从50%
到100%
:
.box {宽度:100px;高度:100px;显示:内联块;边界半径:50%;填充:5px;背景:线性梯度(#ccc,#ccc)内容框,线性梯度(var(--v),蓝色50%,透明0),线性渐变(向右,#f2f2f2 50%,蓝色 0);}
<div class="box" style="--v:-90deg"></div><!-- 50% --><div class="box" style="--v:-45deg"></div><!-- 62.5% --><div class="box" style="--v: 0deg"></div><!-- 75% --><div class="box" style="--v: 45deg"></div><!-- 87.5% --><div class="box" style="--v: 90deg"></div><!-- 100% --><p>公式为[p = (18/5) * x - 270].<small>其中 x 是百分比,p 是度数</small></p><p>对于 x = 80% -->p = 18deg </p><div class="box" style="--v:18deg"></div>
你可以像这样组合两者:
.box {宽度:100px;高度:100px;显示:内联块;边界半径:50%;填充:5px;背景:线性梯度(#ccc,#ccc)内容框,线性梯度(var(--v), #f2f2f2 50%,transparent 0) 0/calc(var(--s)*100%) ,线性梯度(var(--v),蓝色50%,透明0) 0/calc((1 - var(--s))*100%),线性渐变(向右,#f2f2f2 50%,蓝色 0);}
<div class="box" style="--v:-90deg;--s:1"></div><div class="box" style="--v:0deg;--s:1"></div><div class="box" style="--v:90deg;--s:1"></div><div class="box" style="--v:0deg;--s:0"></div><div class="box" style="--v:90deg;--s:0"></div>
现在我们可以像下面这样优化以考虑百分比值:
.box {--v:calc(((18/5) * var(--p) - 90)*1deg);宽度:100px;高度:100px;显示:内联块;边界半径:50%;填充:10px;背景:线性梯度(#ccc,#ccc)内容框,线性梯度(var(--v), #f2f2f2 50%,transparent 0) 0/min(100%,(50 - var(--p))*100%),线性梯度(var(--v),透明50%,蓝色0) 0/min(100%,(var(--p) - 50)*100%),线性渐变(向右,#f2f2f2 50%,蓝色 0);}
<div class="box" style="--p:5;"></div><div class="box" style="--p:20;"></div><div class="box" style="--p:50;"></div><div class="box" style="--p:60;"></div><div class="box" style="--p:75;"></div><div class="box" style="--p:100;"></div>
获取另一个版本的相关问题:
也像下面这样:
.box {--v:calc(((18/5) * var(--p) - 90)*1deg);宽度:100px;高度:100px;显示:内联块;边界半径:50%;填充:10px;背景:线性梯度(var(--v),透明50%,蓝色0) 0/min(100%,(var(--p) - 50)*100%),线性渐变(向右,透明 50%,蓝色 0);-webkit-掩码:线性梯度(var(--v), #f2f2f2 50%,transparent 0) 0/min(100%,(50 - var(--p))*100%),线性梯度(#fff 0 0)内容框,线性梯度(#fff 0 0);-webkit-mask-composite:destination-out;面具复合:排除;}身体 {背景:线性渐变(向右,红色,黄色);}
<div class="box" style="--p:5;"></div><div class="box" style="--p:20;"></div><div class="box" style="--p:50;"></div><div class="box" style="--p:60;"></div><div class="box" style="--p:75;"></div><div class="box" style="--p:100;"></div>
相关:带边框半径的边框渐变
I've found pretty nice "percent pie chart" and want to create it with CSS only. No animation is required. Just static "picture".
I understand If I wanna create this kind of chart I need to use elements like these
The questions are
- How to create element #2 ?
- How to manage shape of element #2 for smaller (5%) or higher percent (80%) values ?
New answer 2021
With some modern techniques we can improve the code. You can have rounded edges and also consider animation:
@property --p{
syntax: '<number>';
inherits: true;
initial-value: 1;
}
.pie {
--p:20; /* the percentage */
--b:22px; /* the thickness */
--c:darkred; /* the color */
--w:150px; /* the size*/
width:var(--w);
aspect-ratio:1/1;
position:relative;
display:inline-grid;
margin:5px;
place-content:center;
font-size:25px;
font-weight:bold;
font-family:sans-serif;
}
.pie:before,
.pie:after {
content:"";
position:absolute;
border-radius:50%;
}
.pie:before {
inset:0;
background:
radial-gradient(farthest-side,var(--c) 98%,#0000) top/var(--b) var(--b) no-repeat,
conic-gradient(var(--c) calc(var(--p)*1%),#0000 0);
-webkit-mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
}
.pie:after {
inset:calc(50% - var(--b)/2);
background:var(--c);
transform:rotate(calc(var(--p)*3.6deg - 90deg)) translate(calc(var(--w)/2 - 50%));
}
.animate {
animation:p 1s .5s both;
}
.no-round:before {
background-size:0 0,auto;
}
.no-round:after {
content:none;
}
@keyframes p{
from{--p:0;}
}
body {
background:#ddd;
}
<div class="pie" style="--p:20"> 20%</div>
<div class="pie" style="--p:40;--c:darkblue;--b:10px"> 40%</div>
<div class="pie no-round" style="--p:60;--c:purple;--b:15px"> 60%</div>
<div class="pie animate" style="--p:80;--c:orange;"> 80%</div>
<div class="pie animate no-round" style="--p:90;--c:lightgreen"> 90%</div>
Old answer
You can do this with multiple background.
From 0%
to 50%
:
.box {
width: 100px;
height: 100px;
display: inline-block;
border-radius: 50%;
padding: 5px;
background:
linear-gradient(#ccc, #ccc) content-box,
linear-gradient(var(--v), #f2f2f2 50%, transparent 0),
linear-gradient(to right, #f2f2f2 50%, blue 0);
}
<div class="box" style="--v:-90deg"></div><!-- 0% -->
<div class="box" style="--v:-45deg"></div><!-- 12.5% -->
<div class="box" style="--v: 0deg"></div><!-- 25% -->
<div class="box" style="--v: 45deg"></div><!-- 37.5% -->
<div class="box" style="--v: 90deg"></div><!-- 50% -->
<p>The formula is [p = (18/5) * x - 90]. <small>Where x is the percentage and p the degree</small></p>
<p>for x = 5% --> p = -72deg </p>
<div class="box" style="--v:-72deg"></div>
From 50%
to 100%
:
.box {
width:100px;
height:100px;
display:inline-block;
border-radius:50%;
padding:5px;
background:
linear-gradient(#ccc,#ccc) content-box,
linear-gradient(var(--v), blue 50%,transparent 0),
linear-gradient(to right, #f2f2f2 50%,blue 0);
}
<div class="box" style="--v:-90deg"></div><!-- 50% -->
<div class="box" style="--v:-45deg"></div><!-- 62.5% -->
<div class="box" style="--v: 0deg"></div><!-- 75% -->
<div class="box" style="--v: 45deg"></div><!-- 87.5% -->
<div class="box" style="--v: 90deg"></div><!-- 100% -->
<p>The formula is [p = (18/5) * x - 270]. <small>Where x is the percentage and p the degree</small></p>
<p>for x = 80% --> p = 18deg </p>
<div class="box" style="--v:18deg"></div>
You can combine both like this:
.box {
width:100px;
height:100px;
display:inline-block;
border-radius:50%;
padding:5px;
background:
linear-gradient(#ccc,#ccc) content-box,
linear-gradient(var(--v), #f2f2f2 50%,transparent 0) 0/calc(var(--s)*100%) ,
linear-gradient(var(--v), blue 50%,transparent 0) 0/calc((1 - var(--s))*100%),
linear-gradient(to right, #f2f2f2 50%,blue 0);
}
<div class="box" style="--v:-90deg;--s:1"></div>
<div class="box" style="--v:0deg;--s:1"></div>
<div class="box" style="--v:90deg;--s:1"></div>
<div class="box" style="--v:0deg;--s:0"></div>
<div class="box" style="--v:90deg;--s:0"></div>
Now we can optimize like below to consider percetange value:
.box {
--v:calc( ((18/5) * var(--p) - 90)*1deg);
width:100px;
height:100px;
display:inline-block;
border-radius:50%;
padding:10px;
background:
linear-gradient(#ccc,#ccc) content-box,
linear-gradient(var(--v), #f2f2f2 50%,transparent 0) 0/min(100%,(50 - var(--p))*100%),
linear-gradient(var(--v), transparent 50%,blue 0) 0/min(100%,(var(--p) - 50)*100%),
linear-gradient(to right, #f2f2f2 50%,blue 0);
}
<div class="box" style="--p:5;"></div>
<div class="box" style="--p:20;"></div>
<div class="box" style="--p:50;"></div>
<div class="box" style="--p:60;"></div>
<div class="box" style="--p:75;"></div>
<div class="box" style="--p:100;"></div>
Related question to get another version: Creating a static pie chart with CSS
We can also consider mask
to add transparency:
.box {
--v:calc( ((18/5) * var(--p) - 90)*1deg);
width:100px;
height:100px;
display:inline-block;
border-radius:50%;
padding:10px;
background:
linear-gradient(var(--v), #f2f2f2 50%,transparent 0) 0/min(100%,(50 - var(--p))*100%),
linear-gradient(var(--v), transparent 50%,blue 0) 0/min(100%,(var(--p) - 50)*100%),
linear-gradient(to right, #f2f2f2 50%,blue 0);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite:destination-out;
mask-composite:exclude;
}
body {
background:linear-gradient(to right,red,yellow);
}
<div class="box" style="--p:5;"></div>
<div class="box" style="--p:20;"></div>
<div class="box" style="--p:50;"></div>
<div class="box" style="--p:60;"></div>
<div class="box" style="--p:75;"></div>
<div class="box" style="--p:100;"></div>
Also like below:
.box {
--v:calc( ((18/5) * var(--p) - 90)*1deg);
width:100px;
height:100px;
display:inline-block;
border-radius:50%;
padding:10px;
background:
linear-gradient(var(--v), transparent 50%,blue 0) 0/min(100%,(var(--p) - 50)*100%),
linear-gradient(to right, transparent 50%,blue 0);
-webkit-mask:
linear-gradient(var(--v), #f2f2f2 50%,transparent 0) 0/min(100%,(50 - var(--p))*100%),
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite:destination-out;
mask-composite:exclude;
}
body {
background:linear-gradient(to right,red,yellow);
}
<div class="box" style="--p:5;"></div>
<div class="box" style="--p:20;"></div>
<div class="box" style="--p:50;"></div>
<div class="box" style="--p:60;"></div>
<div class="box" style="--p:75;"></div>
<div class="box" style="--p:100;"></div>
Related: Border Gradient with Border Radius
这篇关于仅使用 css 的百分比饼图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!