CSS - 用不同颜色的圆形边框

11

有人知道如何在CSS中创建这个效果吗?我知道如何制作四分之一圆形,但不确定如何应用到这种格式中。边框的小块需要使用不同的颜色。

enter image description here


2
SVG对你来说是一个潜在的解决方案吗? - Cyrille
在SVG中可以调整虚线的大小,但是我不确定在CSS中是否可以。至于不同的颜色,我的假设是你可以通过查看css的渐变边框技巧来实现,但要复制你发布的内容,你需要将这两个功能结合起来。 - Eric
SVG是您的完美解决方案,特别是如果您想要为这个美丽的创作添加动画效果。SVG动画实际上非常简单。因此,如果您想要将其制作成加载图像,也可以轻松实现。 - Nick Snick
4个回答

12

你已经得到了很好的答案。

只是为了给你另一种获得这个结果的方式,你可以使用多个背景。这种方法的好消息是你只需要一个div标签即可实现。

.test {
  margin: 25px 0;
  width: 200px;
  height: 200px;
  border-radius: 50%;
  border: 12px solid transparent;
  background-size: 100% 100%, 50% 50%, 50% 50%, 50% 50%, 50% 50%;
  background-repeat: no-repeat;
  background-image: linear-gradient(white, white), 
                    linear-gradient(30deg, red 36%, lightgrey 30%),
                    linear-gradient(120deg, yellow 36%, lightgrey 30%),
                    linear-gradient(300deg, blue 36%, lightgrey 30%),
                    linear-gradient(210deg, green 36%, lightgrey 30%);
  background-position: center center, left top, right top, left bottom, right bottom;
  background-origin: content-box, border-box, border-box, border-box, border-box;
  background-clip: content-box, border-box, border-box, border-box, border-box;
  transform: rotate(30deg);
}
<div class="test"></div>

这些区块可以使用倾斜线性渐变获得,限制在可用空间的四分之一内。我们需要4个这样的区块,改变位置和角度。

在这些区块上方,另一个完全设置为白色的渐变将隐藏中心。

并且将background-origin和clip更改为border-box或content-box,使颜色使用保留给边框的空间。

请注意,此解决方案适用于任何边框/边框半径组合。


11

使用 CSS:

通过 CSS 可以实现(正如 Quantastical 的回答和这里所示),但是,CSS 真的是完成此任务的正确工具吗?我认为不是。原因是使用 CSS 创建这样的形状/效果本身就非常困难,并且除此之外,它们还带有一些限制。例如,下面的代码片段仅在背景为纯色时才起作用。剪辑路径示例在 IE 中完全不受支持,在 FF 中仅与内联 SVG 一起使用。

如果您仍然希望使用 CSS 完成它,则以下是另一种选择。在这里,我们利用 4 个元素(真实或伪装)的 skew 转换,它们都是其父级大小的 50% x 50%。skew 转换会产生类似于扇形的外观,因此看起来更加逼真。分配给这些倾斜元素的背景颜色覆盖在另一个具有完整边框的元素上,并且看起来好像部分边框颜色不同。最后,我们在所有这些元素的顶部添加另一个白色背景的 div 来遮盖圆形的内部区域(仅可见边框)。

.circle {
  position: relative;
  height: 100px;
  width: 100px;
}
.circle, .dummy-border, .border, .dummy-background {
  border-radius: 50%;
  overflow: hidden;
}
.dummy-border, .border, .dummy-background {
  position: absolute;
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
}
.border {
  border: 4px solid #AAA;
  border-radius: 50%;
  z-index: -2;
}
.dummy-background {
  padding: 4px;
  background-color: white;
  background-clip: content-box;
}
.circle:after, .circle:before, .dummy-border:before, .dummy-border:after {
  position: absolute;
  content: '';
  height: 50%;
  width: 50%;
  z-index: -1;
}
.circle:before {
  top: 0%;
  left: 0%;
  background: red;
  transform-origin: right bottom;
  transform: skewY(30deg) skewX(30deg);
}
.circle:after {
  top: 0%;
  left: 50%;
  background: green;
  transform-origin: left bottom;
  transform: skewY(-30deg) skewX(-30deg);
}
.dummy-border:before {
  top: 50%;
  left: 0%;
  background: orange;
  transform-origin: right top;
  transform: skewY(-210deg) skewX(-30deg);
}
.dummy-border:after {
  top: 50%;
  left: 50%;
  background: blue;
  transform-origin: left top;
  transform: skewY(210deg) skewX(30deg);
}
*, *:after, *:before {
  box-sizing: border-box;
}
<div class='circle'>
  <div class='border'></div> <!-- gray border -->
  <div class='dummy-border'></div> <!-- produces colors along with parent's pseudos -->
  <div class='dummy-background'></div> <!-- overlays a white background to mask -->
</div>


使用 SVG:

出于上述原因,我建议您使用 SVG 完成此操作。 SVG 可以轻松创建这种形状和效果,代码易于理解,天生具有响应性。

我的 SVG 技能还不够好,很可能元素数量可以减少。下面的代码段仅是一个示例,用于说明可能实现的效果。

在这里,我们使用 5 个 circle 元素(一个用于灰色边框,其余每个颜色各用一个)。#gray 圆形具有完全灰色边框,而所有其他圆形仅具有部分边框(以所需颜色为准)。利用 stroke-dasharraystroke-dashoffset 属性可生成部分边框。

stroke-dasharray 属性用于通过将描边(颜色)的长度和虚线(透明)的长度作为值来生成虚线边框。对于这种情况,虚线的长度应等于圆的周长(2 * PI * r),而对于描边的长度,我已经使用了值的 1/8 周长。

stroke-dashoffset 属性用于指定描边应该从哪里开始的偏移量。偏移量是从 0 度位置(由 (100%,50%) 表示的点)计算的。通过设置适当的偏移值,可以产生所需的效果。

svg {
  height: 100px;
  width: 100px;
}
circle {
  stroke-width: 4px;
  fill: transparent;
}
#gray{
  stroke: #AAA;
}
#red{
  stroke: red;
  stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
  stroke-dashoffset: -159.75; /* offset of arc from start point (1/2 arc length + 1/4 circumference) */
}
#orange{
  stroke: orange;
  stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
  stroke-dashoffset: -88.75; /* offset of arc from start point (1/2 arc length + 1/4 circumference) */
}
#blue{
  stroke: blue;
  stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
  stroke-dashoffset: -17.75; /* offset of  arc from start point (1/2 of arc length) */
}
#green{
  stroke: green;
  stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
  stroke-dashoffset: -230.75; /* offset of arc from start point (1/2 arc length + 3/4 circumference) */
}
<svg viewBox='0 0 100 100'>
  <circle cx='50' cy='50' r='45' id='gray'/>
  <circle cx='50' cy='50' r='45' id='red'/>
  <circle cx='50' cy='50' r='45' id='green'/>
  <circle cx='50' cy='50' r='45' id='blue'/>
  <circle cx='50' cy='50' r='45' id='orange'/>
</svg>


9
如果您真的想使用CSS来实现此效果,您可以潜在地使用剪切蒙版。但是,这种方法取决于浏览器的兼容性,所以我不知道它有多么有用,除非您在封闭环境中使用。
这种方法也并不完美。剪切路径应该是一个多边形,以确保段边缘朝向圆心而不是与边界框对齐。

#circle, #circle .segment {
  border-color: lightgray;
  border-radius: 50%;
  border-style: solid;
  border-width: 5px;
  box-sizing: border-box;
  height: 100px;
  position: relative;
  width: 100px;
}

#circle .segment {
  -webkit-clip-path: inset(0 40px 50px 40px);
  /*content: ''; EDIT: not needed */
  left: -5px;
  position: absolute;
  top: -5px;
}

#circle .segment:nth-child(1) {border-color: red; transform: rotate(-20deg);}
#circle .segment:nth-child(2) {border-color: blue; transform: rotate(70deg);}
#circle .segment:nth-child(3) {border-color: green; transform: rotate(160deg);}
#circle .segment:nth-child(4) {border-color: yellow; transform: rotate(250deg);}
<div id="circle">
  <div class="segment"></div>
  <div class="segment"></div>
  <div class="segment"></div>
  <div class="segment"></div>
</div>


在 Webkit 浏览器上运行良好。顺便问一下,当 segment 类应用于伪元素时,您使用 content 属性是否有任何原因? - m4n0
哎呀,好发现。我本来想用伪元素:before:after来实现的,这就是为什么有content属性的原因。但后来我改成了嵌套的div,却忘记把它删除了。其实它是不需要的。 - jeffjenx

5

该解决方案使用conic-gradient绘制颜色停止点,并使用具有线性渐变的mask-image来移除内部圆形。

.target {
  width: 60vmin;
  height: 60vmin;
  background: conic-gradient(
    lightgrey 0deg 30deg,
    red 30deg 60deg,
    lightgrey 60deg 120deg,
    yellow 12deg 150deg,
    lightgrey 150deg 210deg,
    green 210deg 240deg,
    lightgrey 240deg 300deg,
    blue 300deg 330deg,
    lightgrey 330deg 360deg
  );
  -webkit-mask-image: radial-gradient(transparent 65%, black 65%);
  mask-image: radial-gradient(transparent 65%, black 65%);
  border-radius: 50%;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  height: 100vh;
}
<div class="target"></div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接