具有边框半径和溢出隐藏属性的元素不能正确地裁剪内容:1像素问题。

6
我正在处理按钮相关的问题。当按钮有圆角并且内部有伪元素(before)用于模拟背景(用于过渡效果)时,我遇到了1像素的问题。伪元素before没有被正确地剪切,你可以看到在按钮边框和填充颜色之间留下了一些空隙。请查看以下示例:
你会发现,在圆角按钮上,边框和填充物之间有一个微小的线/空间。
有什么方法可以消除这个问题而保持相同的结构吗?
编辑1:我知道我可以使用background代替,但在这种情况下我不能这样做。必须通过伪元素来设置背景。
编辑2:该问题可在Win 10、Chrome和Firefox上看到。Firefox使它更加明显。最新版本:Chrome 60.0.3112.78、Firefox 54.0.1
编辑3:修改了代码以显示为什么我不能使用background属性。

a {
  color: black
}

.anibtn {
  display: inline-block;
  overflow: hidden;
  padding: 8px 20px;
  margin: 0 3px 6px 3px;
  text-align: center;
  border: solid 10px black;
  text-decoration: none;
  color: $btncolor;
  white-space: nowrap;
}

.anibtn-round {
  display: inline-block;
  overflow: hidden;
  padding: 8px 20px;
  margin: 0 3px 6px 3px;
  text-align: center;
  border: solid 10px black;
  text-decoration: none;
  color: $btncolor;
  white-space: nowrap;
  border-radius: 50px;
}


.tr-fill-on {
  position: relative;
  transition-duration: .3s;
}

.tr-fill-on:before {
  position: absolute;
  content: '';
  background: black;
  transition-duration: .3s;
  z-index: -1;
  left: 0;
  top: 0;
  width: 0;
  height: 100%;
}
  
.tr-fill-on:hover {
  color: white;
}

.tr-fill-on:hover:before {
  width:100%;
}




.tr-fill2-on{
  color: white;
  position: relative;
  transition-duration: .3s;
}
.tr-fill2-on:before {
  position: absolute;
  content: '';
  background: black;
  transition-duration: .3s;
  z-index: -1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}
.tr-fill2-on:hover {
  color: black;
}

.tr-fill2-on:hover:before {
  width:0;
}
<a href="#" class="anibtn tr-fill-on">Ani Buttons</a>
<a href="#" class="anibtn tr-fill2-on">Ani Buttons</a>
<a href="#" class="anibtn-round tr-fill-on">Ani Buttons</a>
<a href="#" class="anibtn-round tr-fill2-on">Ani Buttons</a>


在 Mac 的 Chrome 上运行良好...哪个浏览器有问题? - Muthu Kumaran
Chrome和Firefox在Win 10上。Firefox使其更加可见。最新版本。 - Varin
我可以在Firefox上看到这个问题... - Muthu Kumaran
这是因为应用于圆角的抗锯齿与放置在具有圆角的实际元素后面的:before伪元素相结合。虽然不确定解决方案可能是什么,但我想把它放在这里...也许它会帮助你/某人找出答案。 - Zoli Szabó
@ZoliSzabó,我刚刚在上面的脚本中增加了边框厚度以提高可见性。谢谢,我会尝试将before元素放在实际按钮上方,并将文本放在两者上方,看看是否有效。编辑-不起作用:( - Varin
3个回答

3

编辑:

我找不到问题,但是我找到了另一种方法来做它 ;)

不要设置border,而是将其设置为border-shadow

.anibtn-round {
  /* border: solid 2px black; */
  box-shadow: inset 0px 0px 0px 2px black;
}

现在那一行将会消失 ;)

前置元素的宽度和高度均为100%。 - Varin
为什么你会踩了我的评论,然后更新了你的问题啊? - Nicholas
在你的评论之前已经进行了编辑,但还是很好的 :) - Varin
1
也许我在你编辑这个的时候正在写 :D。这可能是浏览器渲染(webkit)的问题。 - Nicholas
边框?就像我说的,删除 border:solid 2px black - Nicholas
显示剩余2条评论

2
使用伪元素背景(用于动态效果)和使用实际背景(用于内部边缘的平滑度)并不互斥。如果容器是堆叠上下文的根,则其背景将始终绘制在任何后代之下,即使后代具有负 z-index。将黑色背景设置为按钮(1),使其成为堆叠上下文的根(2),并使伪元素为两种颜色,每个颜色的大小略大于按钮内部区域,并通过动画效果改变其位置而非宽度似乎可以解决白像素问题。
我在按钮背景中使用了单色渐变,以防止在不支持渐变的浏览器中出现黑底黑字的按钮文字(例如 Opera Mini)。如果改为使用transform:translateX或者甚至是transform:translate3d而不是left,则动画效果会更加流畅。

a {
  color: black
}

.anibtn {
  display: inline-block;
  overflow: hidden;
  padding: 8px 20px;
  margin: 0 3px 6px 3px;
  text-align: center;
  border: solid 10px black;
  text-decoration: none;
  color: $btncolor;
  white-space: nowrap;
  background: linear-gradient(black,black); /* 1 */
}

.anibtn-round {
  display: inline-block;
  overflow: hidden;
  padding: 8px 20px;
  margin: 0 3px 6px 3px;
  text-align: center;
  border: solid 10px black;
  text-decoration: none;
  color: $btncolor;
  white-space: nowrap;
  border-radius: 50px;
  background: linear-gradient(black,black); /* 1 */
}


.tr-fill-on {
  position: relative;
  transition-duration: .3s;
  z-index: 1; /* 2 */
}

.tr-fill-on:before {
  position: absolute;
  content: '';
  background: linear-gradient(90deg, white, white 50%, black 50%);
  transition: all .3s;
  z-index: -1;
  left: -1%;
  top: -1%;
  width: 204%;
  height: 102%;
}
  
.tr-fill-on:hover {
  color: white;
}

.tr-fill-on:hover:before {
  left: -103%;
}




.tr-fill2-on{
  color: white;
  position: relative;
  transition-duration: .3s;
  z-index: 1; /* 2 */
}
.tr-fill2-on:before {
  position: absolute;
  content: '';      
  background: linear-gradient(90deg, white, white 50%, black 50%);
  transition: all .3s;
  z-index: -1;
  left: -103%;
  top: -1%;
  width: 204%;
  height: 102%;
}
.tr-fill2-on:hover {
  color: black;
}

.tr-fill2-on:hover:before {
  left: -1%;
}
<a href="#" class="anibtn tr-fill-on">Ani Buttons</a>
<a href="#" class="anibtn tr-fill2-on">Ani Buttons</a>
<a href="#" class="anibtn-round tr-fill-on">Ani Buttons</a>
<a href="#" class="anibtn-round tr-fill2-on">Ani Buttons</a>


我喜欢你的解决方案,我一直在尝试这个想法,但不幸的是,如果容器上有背景图像,则按钮必须处于透明状态。 我最终可能会做的是给按钮设置 transition-duration: 0; 并将背景从黑色切换为透明,这样像素只会在伪元素转换期间可见。 - Varin
我会接受你的答案,因为我使用了这个想法的变体以有点hacky的方式来解决这个问题 :) - Varin

0

如果不需要,您可以删除 overflow: hidden;white-space: nowrap;,希望这能对您有所帮助。

a {
  color: black
}

.anibtn {
  display: inline-block;
  padding: 8px 20px;
  margin: 0 3px 6px 3px;
  text-align: center;
  border: solid 10px black;
  text-decoration: none;
  color: $btncolor;
}

.anibtn-round {
  display: inline-block;
  padding: 8px 20px;
  margin: 0 3px 6px 3px;
  text-align: center;
  border: solid 10px black;
  text-decoration: none;
  color: $btncolor;
  border-radius: 50px;
}


.tr-fill-on {
  position: relative;
  transition-duration: .3s;
}

.tr-fill-on:before {
  position: absolute;
  content: '';
  background: black;
  transition-duration: .3s;
  z-index: -1;
  left: 0;
  top: 0;
  width: 0;
  height: 100%;
}
  
.tr-fill-on:hover {
  color: white;
}

.tr-fill-on:hover:before {
  width:100%;
}




.tr-fill2-on{
  color: white;
  position: relative;
  transition-duration: .3s;
}
.tr-fill2-on:before {
  position: absolute;
  content: '';
  background: black;
  transition-duration: .3s;
  z-index: -1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}
.tr-fill2-on:hover {
  color: black;
}

.tr-fill2-on:hover:before {
  width:0;
}
<a href="#" class="anibtn tr-fill-on">Ani Buttons</a>
<a href="#" class="anibtn tr-fill2-on">Ani Buttons</a>
<a href="#" class="anibtn-round tr-fill-on">Ani Buttons</a>
<a href="#" class="anibtn-round tr-fill2-on">Ani Buttons</a>


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