我已经建立了一个仅CSS的饼图,但是我需要在每个切片之间添加空间,就好像它是一个边框一样。我试图为每个切片添加边框,但这实际上不起作用。关于如何使此CSS饼形图看起来更像下图的任何想法?
这是我的代码:
.palette { height: 48px; width: 48px; } .palette .colorOuter1, .palette .colorOuter2, .palette .colorOuter3, .palette .colorOuter4, .palette .colorOuter5 { height: 200px; width: 200px; border-radius: 50%; position: absolute; top: 0; left: 0; clip: rect(0px, 200px, 200px, 100px); } .palette .colorOuter1 { clip: auto; background: #eee; } .palette .colorOuter2 { transform: rotate(0deg); } .palette .colorOuter2 { transform: rotate(72deg); } .palette .colorOuter3 { transform: rotate(144deg); } .palette .colorOuter4 { transform: rotate(216deg); } .palette .colorOuter5 { transform: rotate(288deg); } .palette .colorInner1, .palette .colorInner2, .palette .colorInner3, .palette .colorInner4, .palette .colorInner5 { position: absolute; top: 0; left: 0; width: 200px; height: 200px; border-radius: 50%; transform: rotate(72deg); } .palette .colorInner1 { background: #5D5E63; clip: rect(0px, 100px, 200px, 0px); } .palette .colorInner2 { background-color: #AEADA9; clip: rect(0px, 100px, 100px, 0px); } .palette .colorInner3 { background-color: #D5C4A8; clip: rect(0px, 100px, 100px, 0px); } .palette .colorInner4 { background-color: #AA875F; clip: rect(0px, 100px, 100px, 0px); } .palette .colorInner5 { background-color: #B7CBC7; clip: rect(0px, 100px, 100px, 0px); } .palette .centerOverlay { position: absolute; border-radius: 50%; top: 60px; left: 60px; background: #fff; width: 80px; height: 80px; display: block; clip: auto; } <div class="palette"> <div class="colorOuter1"> <div class="colorInner1"></div> </div> <div class="colorOuter2"> <div class="colorInner2"></div> </div> <div class="colorOuter3"> <div class="colorInner3"></div> </div> <div class="colorOuter4"> <div class="colorInner4"></div> </div> <div class="colorOuter5"> <div class="colorInner5"></div> </div> <div class="centerOverlay"></div> </div>
首先,我将使用更少的代码来重新创建它,clip-path如下所示:
.palette { height: 200px; width: 200px; position:relative; overflow:hidden; } .palette > * { position:absolute; top:0; left:0; right:0; bottom:0; border:50px solid var(--c,red); border-radius:50%; clip-path:polygon(50% 50%, 50% 0%, 100% 0%,100% 33.745%); } .color1 { transform:rotate(72deg); --c:blue; } .color2 { transform:rotate(144deg); --c:orange; } .color3 { transform:rotate(-72deg); --c:green; } .color4 { transform:rotate(-144deg); --c:purple; } <div class="palette"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> </div>
然后,您可以对元素进行翻译以创建空白:
.palette { height: 200px; width: 200px; position:relative; margin:20px; } .palette > * { position:absolute; top:0; left:0; right:0; bottom:0; border:50px solid var(--c,red); border-radius:50%; clip-path:polygon(50% 50%, 50% 0%, 100% 0%,100% 33.745%); } .color1 { transform:rotate(72deg) translate(5px,-5px); --c:blue; } .color2 { transform:rotate(144deg) translate(5px,-5px); --c:orange; } .color3 { transform:rotate(-72deg) translate(5px,-5px); --c:green; } .color4 { transform:rotate(-144deg) translate(5px,-5px); --c:purple; } .color5 { transform:rotate(0) translate(5px,-5px); --c:red; } <div class="palette"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> </div>
或者,如果要创建缺失零件的效果以保持圆形(如屏幕截图所示),则必须调整剪切路径
.palette { height: 200px; width: 200px; position:relative; overflow:hidden; } .palette > * { position:absolute; top:0; left:0; right:0; bottom:0; border:50px solid var(--c,red); border-radius:50%; clip-path:polygon( calc(50% + 5px) 50%, calc(50% + 5px) 0%, 100% 0%, 100% calc(33.745% - 5px), 50% calc(50% - 5px)); } .color1 { transform:rotate(72deg); --c:blue; } .color2 { transform:rotate(144deg); --c:orange; } .color3 { transform:rotate(-72deg); --c:green; } .color4 { transform:rotate(-144deg); --c:purple; } <div class="palette"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> </div>
使用CSS变量,我们可以轻松处理所有问题
.palette { --g:10px; /* The gap between shapes*/ --s:50px; /* the size*/ height: 200px; width: 200px; position:relative; display:inline-block; overflow:hidden; } .palette > * { position:absolute; top:0; left:0; right:0; bottom:0; border:var(--s) solid var(--c,red); border-radius:50%; clip-path:polygon( calc(50% + var(--g)/2) 50%, calc(50% + var(--g)/2) 0%, 100% 0%, 100% calc(33.745% - var(--g)/2), 50% calc(50% - var(--g)/2)); } .color1 { transform:rotate(72deg); --c:blue; } .color2 { transform:rotate(144deg); --c:orange; } .color3 { transform:rotate(-72deg); --c:green; } .color4 { transform:rotate(-144deg); --c:purple; } <div class="palette"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> </div> <div class="palette" style="--s:40px;--g:20px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> </div> <div class="palette" style="--s:60px;--g:0px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> </div>
使用相同的代码,您可以轻松缩放到任意数量的切片:
8片:
.palette { --g:10px; /* The gap between shapes*/ --s:50px; /* the size*/ height: 200px; width: 200px; position:relative; display:inline-block; overflow:hidden; } .palette > * { position:absolute; top:0; left:0; right:0; bottom:0; border:var(--s) solid var(--c,red); border-radius:50%; clip-path:polygon( calc(50% + var(--g)/2) 50%, calc(50% + var(--g)/2) 0%, 100% 0%, 100% calc(0% - var(--g)/2), 50% calc(50% - var(--g)/2)); } .color1 { transform:rotate(45deg); /* 360/8 */ --c:blue; } .color2 { transform:rotate(90deg); --c:orange; } .color3 { transform:rotate(135deg); --c:green; } .color4 { transform:rotate(180deg); --c:purple; } .color5 { transform:rotate(-45deg); /* 360/8 */ --c:orange; } .color6 { transform:rotate(-90deg); --c:lightblue; } .color7 { transform:rotate(-135deg); --c:pink; } <div class="palette"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> </div> <div class="palette" style="--s:40px;--g:20px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> </div> <div class="palette" style="--s:60px;--g:0px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> </div>
With 3 slices:
.palette { --g:10px; /* The gap between shapes*/ --s:50px; /* the size*/ height: 200px; width: 200px; position:relative; display:inline-block; overflow:hidden; } .palette > * { position:absolute; top:0; left:0; right:0; bottom:0; border:var(--s) solid var(--c,red); border-radius:50%; clip-path:polygon( calc(50% + var(--g)/2) 50%, calc(50% + var(--g)/2) 0%, 100% 0%, 100% calc(78.665% - var(--g)/2), 50% calc(50% - var(--g)/2)); } .color1 { transform:rotate(120deg); --c:blue; } .color2 { transform:rotate(-120deg); --c:orange; } <div class="palette"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> </div> <div class="palette" style="--s:40px;--g:20px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> </div> <div class="palette" style="--s:60px;--g:0px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> </div>
这是用于的魔数背后的公式 clip-path:
clip-path
33.75% = 50% - tan(90deg - 72deg)*50%
0% = 50% - tan(90deg - 45deg)*50%
78.665% = 50% - tan(90deg - 120deg)*50%
因此,N个切片的通用公式为50%(1 - tan(90deg - 360deg/N)) with N in [3 8]。如果N < 3我们有一些琐碎的情况,我们不需要复杂的代码。因为N > 8我们需要一个不同clip-path的公式:50%(1 + tan(360deg/N))
Example with 10 slices:
.palette { --g:10px; /* The gap between shapes*/ --s:50px; /* the size*/ height: 200px; width: 200px; position:relative; display:inline-block; overflow:hidden; } .palette > * { position:absolute; top:0; left:0; right:0; bottom:0; border:var(--s) solid var(--c,red); border-radius:50%; clip-path:polygon( calc(50% + var(--g)/2) 50%, calc(50% + var(--g)/2) 0%, calc(86.327% - var(--g)/2) 0%, 50% calc(50% - var(--g)/2)); } .color1 { transform:rotate(36deg); --c:blue; } .color2 { transform:rotate(72deg); --c:orange; } .color3 { transform:rotate(108deg); --c:green; } .color4 { transform:rotate(144deg); --c:purple; } .color5 { transform:rotate(180deg); --c:lightblue; } .color6 { transform:rotate(-36deg); --c:silver; } .color7 { transform:rotate(-72deg); --c:black; } .color8 { transform:rotate(-108deg); --c:darkgreen; } .color9 { transform:rotate(-144deg); --c:pink; } <div class="palette"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> <div class="color9"></div> <div class="color10"></div> </div> <div class="palette" style="--s:40px;--g:20px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> <div class="color9"></div> <div class="color10"></div> </div> <div class="palette" style="--s:60px;--g:0px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> <div class="color9"></div> <div class="color10"></div> </div>
An idea in case you want to achieve a gradient coloration. This rely on conic-gradient so will not work on Firefox for now:
conic-gradient
.palette { --g:10px; /* The gap between shapes*/ --s:50px; /* the size*/ height: 200px; width: 200px; position:relative; display:inline-block; overflow:hidden; } .palette > * { position:absolute; top:0; left:0; right:0; bottom:0; border:var(--s) solid transparent; background: linear-gradient(#fff,#fff) padding-box, conic-gradient(from calc(-1*var(--d,0deg)), red,blue,green) border-box; border-radius:50%; clip-path:polygon( calc(50% + var(--g)/2) 50%, calc(50% + var(--g)/2) 0%, calc(86.327% - var(--g)/2) 0%, 50% calc(50% - var(--g)/2)); transform:rotate(var(--d,0deg)); } .color1 { --d:36deg; } .color2 { --d:72deg; } .color3 { --d:108deg; } .color4 { --d:144deg; } .color5 { --d:180deg; } .color6 { --d:-36deg; } .color7 { --d:-72deg; } .color8 { --d:-108deg; } .color9 { --d:-144deg; } <div class="palette"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> <div class="color9"></div> <div class="color10"></div> </div> <div class="palette" style="--s:40px;--g:20px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> <div class="color9"></div> <div class="color10"></div> </div> <div class="palette" style="--s:60px;--g:0px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> <div class="color9"></div> <div class="color10"></div> </div>
You can simulate another gradient coloration with linear-gradient and you will have better support:
linear-gradient
.palette { --g:10px; /* The gap between shapes*/ --s:50px; /* the size*/ height: 200px; width: 200px; position:relative; display:inline-block; overflow:hidden; } .palette > * { position:absolute; top:0; left:0; right:0; bottom:0; padding:var(--s); background: linear-gradient(#fff,#fff) content-box, linear-gradient(red,blue,green) padding-box; border-radius:50%; clip-path:polygon( calc(50% + var(--g)/2) 50%, calc(50% + var(--g)/2) 0%, 100% 0%, 100% calc(0% - var(--g)/2), 50% calc(50% - var(--g)/2)); transform:rotate(var(--d,0deg)); } .palette > *:before { content:""; position:absolute; top:0; left:0; right:0; bottom:0; padding:inherit; background:inherit; transform:rotate(calc(-1*var(--d,0deg))); border-radius:50%; } .color1 { --d:45deg; } .color2 { --d:90deg; } .color3 { --d:135deg; } .color4 { --d:180deg; } .color5 { --d:-45deg; } .color6 { --d:-90deg; } .color7 { --d:-135deg; } <div class="palette"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> </div> <div class="palette" style="--s:40px;--g:20px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> </div> <div class="palette" style="--s:60px;--g:0px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> </div>
We can add mask for full transparency:
.palette { --g:10px; /* The gap between shapes*/ --s:50px; /* the size*/ height: 200px; width: 200px; position:relative; display:inline-block; overflow:hidden; } .palette > * { position:absolute; top:0; left:0; right:0; bottom:0; background:linear-gradient(red,blue,green) padding-box; -webkit-mask:radial-gradient(farthest-side,transparent calc(99% - var(--s)),#fff calc(100% - var(--s))); mask:radial-gradient(farthest-side,transparent calc(99% - var(--s)),#fff calc(100% - var(--s))); border-radius:50%; clip-path:polygon( calc(50% + var(--g)/2) 50%, calc(50% + var(--g)/2) 0%, 100% 0%, 100% calc(0% - var(--g)/2), 50% calc(50% - var(--g)/2)); transform:rotate(var(--d,0deg)); } .palette > *:before { content:""; position:absolute; top:0; left:0; right:0; bottom:0; background:inherit; transform:rotate(calc(-1*var(--d,0deg))); border-radius:50%; } .color1 { --d:45deg; } .color2 { --d:90deg; } .color3 { --d:135deg; } .color4 { --d:180deg; } .color5 { --d:-45deg; } .color6 { --d:-90deg; } .color7 { --d:-135deg; } body { background:linear-gradient(to left,grey,#fff); } <div class="palette"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> </div> <div class="palette" style="--s:40px;--g:20px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> </div> <div class="palette" style="--s:60px;--g:0px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> </div>
Same thing with the conic-gradient:
.palette { --g:10px; /* The gap between shapes*/ --s:50px; /* the size*/ height: 200px; width: 200px; position:relative; display:inline-block; overflow:hidden; } .palette > * { position:absolute; top:0; left:0; right:0; bottom:0; background: conic-gradient(from calc(-1*var(--d,0deg)), red,blue,green); -webkit-mask:radial-gradient(farthest-side,transparent calc(99% - var(--s)),#fff calc(100% - var(--s))); mask:radial-gradient(farthest-side,transparent calc(99% - var(--s)),#fff calc(100% - var(--s))); border-radius:50%; clip-path:polygon( calc(50% + var(--g)/2) 50%, calc(50% + var(--g)/2) 0%, calc(86.327% - var(--g)/2) 0%, 50% calc(50% - var(--g)/2)); transform:rotate(var(--d,0deg)); } .color1 { --d:36deg; } .color2 { --d:72deg; } .color3 { --d:108deg; } .color4 { --d:144deg; } .color5 { --d:180deg; } .color6 { --d:-36deg; } .color7 { --d:-72deg; } .color8 { --d:-108deg; } .color9 { --d:-144deg; } body { background:linear-gradient(to left,grey,white); } <div class="palette"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> <div class="color9"></div> <div class="color10"></div> </div> <div class="palette" style="--s:40px;--g:20px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> <div class="color9"></div> <div class="color10"></div> </div> <div class="palette" style="--s:60px;--g:0px"> <div class="color1"></div> <div class="color2"></div> <div class="color3"></div> <div class="color4"></div> <div class="color5"></div> <div class="color6"></div> <div class="color7"></div> <div class="color8"></div> <div class="color9"></div> <div class="color10"></div> </div>
For IE Support
Here is another idea with more support that should work for old browsers:
#colorWheel { width: 300px; height: 300px; position: relative; border-radius: 100%; overflow: hidden; } #colorWheel:after { content: ""; position: absolute; border-radius: inherit; /* adjust the value to control the thickness*/ top: 30px; left: 30px; right: 30px; bottom: 30px; /**/ background: #fff; } #colorWheel span { position: absolute; border-style: solid; border-width: 150px 36px; /*adjust the 36px to control the distance*/ left: 50%; top: 50%; color: transparent; } span:nth-child(1) { border-top-color: #bf6040; transform: translate(-50%, -50%) rotate(36deg); } span:nth-child(2) { border-top-color: #bf8040; transform: translate(-50%, -50%) rotate(72deg); } span:nth-child(3) { border-top-color: #bf9f40; transform: translate(-50%, -50%) rotate(108deg); } span:nth-child(4) { border-top-color: #bfbf40; transform: translate(-50%, -50%) rotate(144deg); } span:nth-child(5) { border-top-color: #9fbf40; transform: translate(-50%, -50%) rotate(180deg); } span:nth-child(6) { border-top-color: #80bf40; transform: translate(-50%, -50%) rotate(216deg); } span:nth-child(7) { border-top-color: #60bf40; transform: translate(-50%, -50%) rotate(252deg); } span:nth-child(8) { border-top-color: #40bf40; transform: translate(-50%, -50%) rotate(288deg); } span:nth-child(9) { border-top-color: #40bf60; transform: translate(-50%, -50%) rotate(324deg); } span:nth-child(10) { border-top-color: #40bf80; transform: translate(-50%, -50%) rotate(360deg); } <div id="colorWheel"> <span></span> <span></span> <span></span> <span></span> <span></span> <span></span> <span></span> <span></span> <span></span> <span></span> </div>
Here is a SASS code to easily generate the shape:
$num:10; @for $i from 1 through $num { span:nth-child(#{$i}) { border-top-color: hsl($i * 15, 50%, 50%); transform: translate(-50%,-50%) rotate($i * (360deg/$num)); } } #colorWheel { width: 300px; height: 300px; position: relative; border-radius: 100%; overflow: hidden; } #colorWheel:after { content:""; position:absolute; border-radius:50%; /* adjust the value to control the thickness*/ top:30px; left:30px; right:30px; bottom:30px; /**/ background:#fff; } #colorWheel span { position: absolute; border-style: solid; border-width: 150px 36px; /*adjust the 36px to control the distance*/ left: 50%; top: 50%; color:transparent; }
Related: Sass/CSS color wheel