【问题标题】:Is it possible to create this shape (two partial circles joined together) with CSS?是否可以使用 CSS 创建这种形状(两个部分圆连接在一起)?
【发布时间】:2023-03-19 09:10:02
【问题描述】:

我试图用 CSS 为两个 div 完成这个边框:

我尝试只使用border-radius,但两个部分圆圈没有压在一起:http://jsfiddle.net/uwz6L79w/

 .left {
   position: absolute;
   left: 0;
   top: 0;
   width: 100px;
   height: 100px;
   border-width: 4px;
   border-color: black white black black;
   border-style: solid;
   border-radius: 60px
 }
 .right {
   position: absolute;
   left: 104px;
   top: 0;
   width: 100px;
   height: 100px;
   border-width: 4px;
   border-color: black black black white;
   border-style: solid;
   border-radius: 60px;
 }
<div class="left"></div>
<div class="right"></div>

我可以将它们进一步压在一起,但我必须让一个 div 与另一个重叠,如下所示:http://jsfiddle.net/uwz6L79w/1/。

.left {
  position: absolute;
  left: 0;
  top: 0;
  width: 100px;
  height: 100px;
  border-width: 4px;
  border-color: black white black black;
  border-style: solid;
  border-radius: 60px
}
.right {
  position: absolute;
  left: 70px;
  top: 0;
  width: 100px;
  height: 100px;
  border-width: 4px;
  border-color: black black black white;
  border-style: solid;
  border-radius: 60px;
  background: #f2f2f2;
}
<div class="left"></div>
<div class="right"></div>

有谁知道我如何在不重叠 div 的情况下做到这一点?

【问题讨论】:

  • 是的,有可能。看看this link 并尝试从 infinity 开始。
  • 你也可以用伪元素重叠来做到这一点。
  • 你的第二个 sn-p 对我来说很好。您能否提供一张屏幕截图,说明您使用的是什么浏览器?
  • @Bergi:OP 不希望它重叠。也就是说,如果您向其中一个div 添加背景,您会看到它们已将第二个div 的一部分置于第一个之上。
  • @Harry:是的,但是示例没有背景,所以我不确定问题出在哪里。也许有比避免重叠更好的方法来解决问题?

标签: html css css-shapes


【解决方案1】:

SVG

这也可以使用 SVG。

SVG 版本很短,主要只需要一个 Arc 命令来控制它的形状、大小和位置。

<svg width="50%" viewbox="0 0 100 50">
  <path d="M50,35 
           a20,20 0 1,0 0,-20 
           a20,20 0 1,0 0,20z" 
        fill="white" 
        stroke="black">
  </path>
</svg>

SVG 代表可缩放矢量图形。 Web 浏览器将其视为图像,但您可以在 SVG 中添加文本和普通 HTML 元素。

它在所有浏览器中都得到很好的支持,可以在此处查看:CanIUse

【讨论】:

  • 您可以通过仅使用一个路径元素在它们之间获得更简洁的连接。
  • @Anko 不知道为什么我一开始就没有想到这一点:P。为建议喝彩并修改了我的答案:)
【解决方案2】:

使用边框: 推荐

您可以像在第二个 sn-p 中那样执行此操作,并使用下面的 sn-p 中的定位来避免两个 div 元素重叠。这里的圆是由伪元素产生的,重叠的部分是在它们的父级上使用overflow: hidden 切掉的。

这里需要注意的一点是,任何悬停效果都应该添加到伪元素而不是父元素上。这是因为如果:hover 附加到父级,那么即使悬停在圆圈外也会触发(因为父级仍然是正方形)。

在此答案中提供的所有三种解决方案中,这是具有最佳浏览器支持并且即使在 IE8 中也可以使用的一种。因此,这是推荐的。

.left, .right {
  position: relative;
  float: left;
  height: 200px;
  width: 200px;
  /* border: 1px solid; uncomment to see that they aren't overlapped */
  overflow: hidden;
}
.left:after, .right:after {
  position: absolute;
  content: '';
  height: calc(100% - 12px); /* 12px because of 6px border on either side */
  width: calc(100% - 12px); /* 12px because of 6px border on either side */
  border-radius: 50%;
  border: 6px solid gray;
}
.left:after { right: -20px; }
.right:after { left: -20px; }
<div class='left'></div>
<div class='right'></div>

使用径向渐变:

如果您不想在父级上使用伪元素和overflow: hidden,那么您还可以使用radial-gradient 背景图像来生成圆圈并定位它们,以便它们最终产生所需的效果.以下是此方法的示例 sn-p。

这种方法的缺点是low browser support for radial-gradient。它不适用于 IE9 及更低版本。另外,径向渐变产生的圆圈通常是锯齿状的(粗糙的边缘),当我们修改颜色停止位置使其更平滑时,它会产生轻微的模糊外观。

.left, .right {
  float: left;
  height: 200px;
  width: 200px;
  /*border: 1px solid;  uncomment to see that they aren't overlapped */
}

/* generally the below code should be enough to produce 6px thick circular border
.left {
  background: radial-gradient(circle at 70% 50%, transparent calc(50% - 3px), gray calc(50% - 3px), gray calc(50% + 3px), transparent calc(50% + 3px));
}
.right {
  background: radial-gradient(circle at 30% 50%, transparent calc(50% - 3px), gray calc(50% - 3px), gray calc(50% + 3px), transparent calc(50% + 3px));
}
*/

/* but it produces jagged edges and so we can change the color stops a bit like below
   this produces smoother circles but the disadvantage is that they'd look a bit blurred */
.left {
  background: radial-gradient(circle at 70% 50%, transparent calc(50% - 4px), gray calc(50% - 2px), gray calc(50% + 2px), transparent calc(50% + 4px));
}
.right {
  background: radial-gradient(circle at 30% 50%, transparent calc(50% - 4px), gray calc(50% - 2px), gray calc(50% + 2px), transparent calc(50% + 4px));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='left'></div>
<div class='right'></div>

使用剪辑路径 (CSS/SVG):

可以使用的另一种方法是使用clip-path。这种方法的优点是hover 效果只会在光标在圆圈内时触发(如 sn-p 所示)。这是因为不需要的部分被剪掉了。

缺点又是poor browser support。 clip-path 的 CSS 版本仅在 Webkit 中受支持,但在 Firefox、IE 中不支持,而 SVG 版本(使用内联 SVG)在 Webkit、Firefox 中受支持,但在 IE 中不支持。

.left, .right {
  float: left;
  height: 200px;
  width: 200px;
  border-radius: 50%;
  border: 6px solid gray;
}

/* CSS Clip Path - not supported by FF and IE */
.left.css-clip {
  clip-path: polygon(0% 0%, 80% 0%, 80% 100%, 0% 100%);
}
.right.css-clip {
  margin-left: -86px;  /* 20% width * 2 (which is the clipped space) - border width */
  clip-path: polygon(20% 0%, 100% 0%, 100% 100%, 20% 100%);
}

/* SVG Clip Path - supported by Webkit, FF but not IE */
.left.svg-clip {
  clip-path: url(#clipper-left);
}
.right.svg-clip {
  margin-left: -86px;  /* 20% width * 2 (which is the clipped space) - border width */
  clip-path: url(#clipper-right);
}

/* Just for demo */

h3{ clear: both; }
.left:hover, .right:hover{ background: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>

<h3>CSS Clip Path</h3>
<div class='left css-clip'></div>
<div class='right css-clip'></div>

<h3>SVG Clip Path</h3>
<div class='left svg-clip'></div>
<div class='right svg-clip'></div>

<!-- Inline SVG for SVG Clip Path -->
<svg width='0' height='0'>
  <defs>
    <clipPath id='clipper-left' clipPathUnits='objectBoundingBox'>
      <path d='M0,0 .8,0 .8,1 0,1z' />
      </clipPath>
    <clipPath id='clipper-right' clipPathUnits='objectBoundingBox'>
      <path d='M.2,0 1,0 1,1 .2,1z' />
      </clipPath>
    </defs>
  </svg>

【讨论】:

  • 第二种方案有毛边,不知道有没有办法解决这个问题?
  • @jaunt:通过调整渐变的色标百分比可以在一定程度上减少它,但我认为我们不能完全摆脱它。
  • @jaunt:我已经更新了第二个解决方案以产生更平滑的圆(更改了颜色停止百分比),但这似乎是我们可以用径向渐变做的最大值。
  • 啊,好吧,我明白你在说什么了,这样看起来确实更好
  • @slebetman:画圆圈 - 是的。但我没有在那里画圈。我正在调整使用边框创建的用户圈子,以克服不重叠和剪裁不必要的部分是实现它的一种方法,同时仍保留 OP 的原始工作。
【解决方案3】:

这是一个只使用一个 &lt;div&gt; 的解决方案。

  1. .shape 是一个带有10px 红色边框的透明圆圈。
  2. .shape::before 是一个带有10px 红色边框的不透明白色圆圈。
  3. .shape::after 是一个不透明的白色圆圈(无边框)。

.shape {
margin: 6px auto;
}

.shape, .shape::before, .shape::after {
display: block;
position: relative;
width: 160px;
height: 160px;
border-radius: 160px;
}

.shape, .shape::before {
border: 10px solid #f00;
}

.shape::before, .shape::after {
content: "";
background-color: rgba(255, 255, 255, 1);
}

.shape::before {
top: -10px;
left: -150px;
}

.shape::after {
top: -180px;
}
&lt;div class="shape"&gt;&lt;/div&gt;

【讨论】:

  • 您应该使用#FFF、#FFFFFF、white 或rgb(255, 255, 255) 而不是rgba(255, 255, 255, 1)。由于您指定的是没有不透明度的颜色,因此不需要rgba。它可能会让浏览器更加努力地工作。为了简化对 IE8 的支持,您可以使用 :before 和 :after。有很多库可以在 IE8 上添加对圆角边框的支持。但是,除此之外,即使在 IE8 上,您的解决方案也有效(具有上述更改)!!! (圆形边框除外)。这比 SVG 解决方案要优越得多!
  • @IsmaelMiguel:我不确定您是仅与 SVG 还是与此线程上的所有其他答案进行比较,但 Jeff 和我的答案中的第一个 sn-p 也适用于 IE8。如果没有和他们比较,请见谅。
  • @Harry 哦,不。我只是在比较仅 SVG 的解决方案。此外,这略优于其他答案,因为它减少了空元素的数量。有些人对空标签非常严格。但这也适用于&lt;span&gt;。没有人抱怨空的&lt;span&gt;,对吧?
  • 公平点的伙伴。我选择了两个div 元素,纯粹是因为 OP 提出了这个问题 - 两个 div 的边框。我假设他们已经有两个div,只是希望以这种方式设置边框。
  • @Rounin:我喜欢你的回答,绝对没有错。您的回答确实增加了价值。
【解决方案4】:

这是我想出的一个简单示例。我没有在不同的浏览器中测试过,但它应该得到很好的支持。

HTML:

<div class="one"></div>
<div class="two"></div>

CSS:

div {
  background: #fff;
  border-radius: 50%;
  float: left;
  height: 100px;
  position: relative;
  width: 100px;
}

.one:after,
.two:after{
  /* adjust this to set the border color */
  background: #666;
  border-radius: 50%;
  content: "";
  position: absolute;
  z-index: -1;
  /* adjust these to set the border width */
  top: -5px;
  right: -5px;
  bottom: -5px;
  left: -5px;
}

.two {
  /* adjust this to set the overlap of the circles */
  margin-left: -20px;
}

Live Demo

【讨论】:

【解决方案5】:

我回来回答这个问题(6 周后),纯粹是因为最高投票的答案激起了我对 svg 的学术好奇心,我很少遇到也从未花时间学习。

由于我现在正在学习 svg,这个问题(这让我一开始就开始学习它)似乎是尝试一些新技能的理想挑战。

所以这是一个替代 svg 解决方案,相当于我上面的单个&lt;div&gt; css 解决方案:

svg {
width: 310px;
height: 180px;
}

svg circle {
stroke: rgb(255,0,0);
stroke-width: 10;
fill: rgb(255,255,255);
}

svg circle:nth-of-type(3) {
stroke: rgb(255,255,255);
}
<svg viewbox="0 0 310 180">
<circle cx="90" cy="90" r="80" />
<circle cx="220" cy="90" r="80" />
<circle cx="90" cy="90" r="70" />
</svg>

【讨论】:

  • 不得不说这是一个非常好的补充:)。干得好+1
猜你喜欢
  • 2015-12-04
  • 2017-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-13
  • 1970-01-01
  • 2013-11-01
相关资源
最近更新 更多