由于边框半径为 50% 的包装元素上的背景颜色而显示锯齿状“边框”;

Posted

技术标签:

【中文标题】由于边框半径为 50% 的包装元素上的背景颜色而显示锯齿状“边框”;【英文标题】:Jagged "border" showing due to background colour on wrapper element with border-radius: 50%; 【发布时间】:2015-02-16 00:40:48 【问题描述】:

当我尝试制作动画人物(悬停时的过渡)时,我发现我的<figure> 的背景在我应用border-radius: 50% 时显示在边缘附近,即使我的图像应该占用所有可用空间。

有关说明问题的快速演示,请查看http://codepen.io/anon/pen/KwMMKz

HTML

<figure>
  <img src="http://placehold.it/400x400" alt>
  <figcaption>Demo</figcaption>
</figure>

CSS

figure 
  background-color: red;
  width: 400px;
  height: 400px;
  border-radius: 50%;
  overflow: hidden;
  position: relative; /* For caption */



img 
  border-radius: 50%; /* Forced on image for smooth transition */
  width: 100%;
  transition: opacity 1s ease-out;


figcaption 
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  color: hotpink;
  text-align: center;
  transition: top 1s ease-out;

figure:hover img 
  opacity: 0;

figure:hover figcaption 
  top: 50%;

请注意:我知道将背景色放在 figure:hover 上是一种解决方法,但我更感兴趣的是为什么会出现这种“锯齿状边框”般的外观.

我的猜测是它与浏览器的 AA 渲染(或相关内容)有关,并且它对待 &lt;figure&gt; 元素与 &lt;img&gt; 等媒体元素不同,但我找不到任何证据这个在线。这是一个错误,它是一个“功能”,还是我可以实际修复的东西?

最后,我也知道我可以在这里使用transform: translateY(); 来制作动画,但这不是我的问题的一部分,所以请不要提供它作为答案。

更新 17/12 14:03

看来这个问题并不是border-radius: 50% 独有的。当任何包装元素将border-radiusoverflow: hidden 结合使用时,当包装器包含等于或大于包装器尺寸的内容时,就会出现此问题。

更新 17/12 14:14

在包装元素上使用overflow: hidden,在包含的图像(或任何其他子元素)上使用border-radius似乎都不是造成这种情况的原因,因为它们可以互换并且像素化边缘将仍然出现。

这似乎表明这个问题完全是由于 2 个 DOM 元素位于完全相同的位置,当任何类型的边框半径应用于包装元素并且子元素的可见区域仅限于父母的。

【问题讨论】:

这似乎和这篇文章是同一个问题:Pixelated edge around a CSS Circle with overflow: hidden; 您的问题是关于非常亮(1px 红色边框)还是关于悬停时灰色区域是正方形(淡出时)而不是圆形? @web-tiki 它可能与同一个核心问题有关,但我在该帖子中看不到任何回复来解释它发生的原因以及它是否是一个错误。为什么这只发生这种像素化效果只发生在边界半径上:50% 当两个元素应该在同一位置相遇时?我想不出发生这种情况的任何充分理由。 @marczking:我的问题与非常浅的红色边框有关。 @SimonV。是的,我明白这一点,这就是为什么我没有将这个问题作为重复问题关闭。问题相同,但问题不同。 【参考方案1】:

我也遇到了同样的问题,最后使用了伪元素而不是背景,有点像这样:

figure::before 
  content: '';
  display: block;
  background-color: red;
  width: 400px;
  height: 400px;
  transform: scale(0.997);
  border-radius: 50%;

这使我可以创建“伪背景”,后来我使用 transform: scale(0.997); 将其缩小了一点,因此它的大小相同,但略低于可见边缘。当然,在您的情况下,您还需要绝对定位图像,这样它就不会被这个 ::before 推到下面。

【讨论】:

【参考方案2】:

看起来它确实是浏览器如何处理border-radius 的一个“功能”,可以为容器的圆角提供平滑的边缘。通过设置 img 背景颜色可以看到,图像背景以相同的方式进行抗锯齿处理(但因为它是透明的,所以没有效果)。

当边框被消除锯齿时,它会“渗入”背景以柔化边缘,因此您会在图像周围看到一个“锯齿状”环,就像您在月球周围看到日冕一样日全食。

问题总是存在的,无论抗锯齿对象是否被覆盖,如果您要画一个圆圈然后对其进行抗锯齿处理,您会看到圆圈比抗锯齿版本略窄。大多数抗锯齿算法会聚合对象的周围像素,而不是其中包含的像素。

要克服它,您需要使图像足够大以覆盖抗锯齿边缘占用的空间,或者缩小容器以使抗锯齿区域小于图像。

【讨论】:

OP 明确指出 ------> “我知道将背景颜色放在 figure:hover 上是一种解决方法,但我对原因更感兴趣为什么会出现这种类似“锯齿状边框”的外观”,这意味着 OP 正在寻找原因而不是解决方案。 谢谢,但我不明白如何为悬停状态添加背景颜色,当然它必须在图像上。无论如何都要更新以解释发生了什么。 @Mauro:这不是真的。如果添加 figure:hover background-color: red; 而不是在图 上定义它,您将处理锯齿状边缘。话虽如此,这与我的问题无关,因为我在问为什么会发生这种情况,而不是我自己能想到的一些解决方法。 @SimonV。删除了黑客。希望现在的解释经得起推敲。【参考方案3】:

您可以添加一个不透明度为 0 的新标签,然后让该标签随着图像淡出而淡入。

figure 
  width: 400px;
  height: 400px;
  border-radius: 50%;
  overflow: hidden;
  position: relative; /* For caption */


background 
  background-color: red;
  width: 400px;
  height: 400px;
  border-radius: 50%;
  overflow: hidden;
  opacity: 0;
  position: fixed;
  z-index: 5;
  transition: opacity 1s ease-out;


img 
  border-radius: 50%; /* Forced on image for smooth transition */
  width: 100%;
  transition: opacity 1s ease-out;
  position: relative;
  z-index: 100;


figcaption 
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  color: hotpink;
  text-align: center;
  transition: top 1s ease-out;
  z-index: 10000;

figure:hover img 
  opacity: 0;

figure:hover background 
  opacity: 1;

figure:hover figcaption 
  top: 50%;
<figure>
  <background></background>
  <img src="http://placehold.it/400x400" alt>
  <figcaption>Demo</figcaption>
</figure>

请注意,我添加了background 标签并从figure 中删除了background-color

【讨论】:

【参考方案4】:

http://codepen.io/marczking/pen/KwMgaR

所以在玩了之后(使用了background-image 和伪元素,没有任何改变......)你注意到这个浅色边框只有在你应用圆角时才可见。所以我在这里假设它必须做浏览器如何呈现 CSS,CSS 规则没有错^^)

<figure>
  <figcaption>Demo</figcaption>
</figure>

figure 
  background-color: red;
  width: 400px;
  height: 400px;
  border-radius: 100px;
  position: relative; /* For caption */


figure::before 
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background: url("http://placehold.it/400x400") no-repeat;
  border-radius: 100px; /* Forced on image for smooth transition */
  transition: opacity 1s ease-out;


figcaption 
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  color: hotpink;
  text-align: center;
  transition: top 1s ease-out;

figure:hover::before 
  opacity: 0;

figure:hover figcaption 
  top: 50%;

【讨论】:

marczking:我知道只有在使用 50% 作为边界半径时才会出现这种情况,并且可能与浏览器渲染有关。我在所有相关浏览器中对此进行了测试,它们都显示相同的结果。只是怀疑所有浏览器都会犯同样的“错误”,所以如果有人至少可以确认它确实与浏览器渲染有关,那就太好了。 在我上面的笔中,当使用 100px 而不是 50% 时也会出现这种情况,边框半径的大小似乎无关紧要 marczking:你似乎是对的。所以基本上,当任何包装元素结合使用边界半径时会发生这种情况溢出:隐藏......这只是浏览器不支持的东西吗? 在我的示例中,我也不使用overflow: hidden 只是为了减少它与规则组合无关的可能性 再一次,你似乎是对的。包装器上的溢出:隐藏必须保留(仅显示可见区域)或包含元素上的边框半径需要保留。所以基本上,它与任何一个都没有关系,但更多的是关于 2 个元素位于完全相同的位置并带有弯曲的边框。我相应地更新了问题。

以上是关于由于边框半径为 50% 的包装元素上的背景颜色而显示锯齿状“边框”;的主要内容,如果未能解决你的问题,请参考以下文章

带有白色边框的警报控制器

为圆形图像添加2种颜色的边框

边框半径 + 背景颜色 == 裁剪边框

添加边框半径后为应用栏背景着色

如何仅将边框半径用于 1 个角(react-native)?

背景颜色和边框半径属性在 React Native 中无法协同工作 - Android