高DPI显示器上的div背景和边框之间的0-1px间距变化

时间:2019-05-30 01:40:16

标签: css css3 google-chrome retina-display dpi

这是我在CSS中创建的按钮的隔离示例。它具有带渐变的1px边框和背景渐变。将背景渐变实现为伪元素,以使其悬停时其不透明性消失。

https://codepen.io/anon/pen/wbYoeo?editors=1100

.Button
{
  width: 200px;
  height: 30px;
  cursor: pointer;
    padding: 0.8rem;
    border-style: solid;
    border-image: linear-gradient(
        to right,
        green 0%,
        blue 100%);
    border-image-slice: 1;
    border-width: 1px;
    position: relative;
  margin-top: 10px;
    transition: color 0.2s;
}

.Button::before
{
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    background-image: linear-gradient(
        to right,
        green 0%,
        blue 100%);
    opacity: 0.5;
    transition: opacity 0.2s;
}

在不同DPI的监视器之间,按钮的渲染效果并不相同。在Windows上的Chrome中以不同的DPI比例呈现的按钮的屏幕截图:

100% DPI-scaled monitor, rendering correctly with no gap.

150% DPI-scaled monitor, showing a gap between the background and border.

175% DPI-scaled monitor, showing a gap between the background and border.

200% DPI-scaled monitor, rendering correctly with no gap.

我尝试了几种渲染按钮的策略,但它们都会导致差距:

  • linear-gradientborder-image上都尝试使用带有渐变的image而不是background-image
  • 试图对背景渐变使用显式div代替伪元素。
  • 试图对背景渐变使用显式div而不是伪元素,并且还使用了实心左右边界以及顶部和底部边界具有线性渐变背景的:: before和:: after伪元素。

1 个答案:

答案 0 :(得分:1)

原因?

我会(未经教育)猜测这是缩放时由子像素引起的。它不能是像素的一小部分,因此会选择整个像素值。父母计算出的值比在某些比例上给孩子的值大1px。

解决方法

将边框从按钮div本身上取下,然后将其放在::after伪元素上,以便边框和背景都是孩子。现在,边框似乎与背景渐变一致缩放。

示例

.Button {
  width: 200px;
  height: 30px;
  cursor: pointer;
  padding: 0.8rem;
  position: relative;
  margin-top: 10px;
  transition: color 0.2s;
}

.Button::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background-image: linear-gradient( to right, green 0%, blue 100%);
  opacity: 0.2;
  transition: opacity 0.2s;
}

.Button:hover::before {
  opacity: 0.5;
}

.Button:active::before {
  opacity: 1;
}

.Button::after {
  content: '';
  border-style: solid;
  border-image: linear-gradient( to right, green 0%, blue 100%);
  border-image-slice: 1;
  border-width: 1px;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  top: 0;
}

html {
  height: 100%;
  display: table;
  margin: auto;
}

body {
  background: black;
  display: table-cell;
  vertical-align: middle;
  color: white;
  font-family: sans-serif;
}
Click it:
<div class="Button"></div>