子像素在浏览器中计算和呈现的方式不同

Kam*_*her 17 css rendering cross-browser css3 subpixel

目的:

我正在处理类似于此的代码,以创建一个输入字段具有嵌入按钮的组件:

http://codepen.io/anon/pen/pgwbWG?editors=110

如您所见,按钮绝对定位topbottom设置为0,以实现100%高度元素.

另外需要注意的是,文本输入的边框必须保持可见,并且还要包裹按钮.为了达到这个目的,我margin: 1px按钮上添加了一个,以便(应该是)空间显示周围的文本输入红色边框(通常在输入字段内容无效时).

问题:

就是在Firefox上它(大部分)正确呈现,而在Chrome上(显然在最新的Safari上)它会按钮底部1px的间隙.

CSS似乎确定,但它似乎是在渲染,在底部或按钮的上边距是不是真的1px的计算/舍入的问题(可以看到它检查元素).此外,输入的填充似乎也会影响到.

在不同的缩放率下,它会在按钮的顶部或底部添加或删除1px的边距,从而产生1px间隙或覆盖边框.

当我设置按钮边距时0px,底部边距是固定的,但我松开顶部的1px边距,完成覆盖文本输入的红色边框.

例子:

也许我不明白或解释它太冗长,所以这里是错误的一些截图,从不同的缩放在Chrome(注意CSS始终是相同的):

在此输入图像描述 在此输入图像描述 在此输入图像描述 在此输入图像描述

解决方案:

我无法找到跨浏览器的解决方案.如何处理它并获得一致的组件?(请不要使用Javascript)

val*_*als 9

如您所知,问题源于浏览器之间的子像素演算的不同方法

例如,在Chrome中,边框可以具有小数尺寸,但边距处理不同(作为整数).

我没有Chrome团队提供有关它的文档,但它可以在开发工具中看到:

开发工具捕获

AFAIK,没有办法改变这种状况.

相反,您可以将按钮中边距的使用转移到边框.

由于您需要为输入的1px边框获取空间,请在按钮中执行相同操作,设置1px边框(而不是边距),并将其设置为透明.

剩下的技巧是将background-clip属性设置为padding框,这样透明度就不会受到背景的影响

Chrome中还有另一个错误,当浏览器缩放时,以这种精度级别表示的填充不可靠.我在片段中更改了此内容.

由于我们使用边框按钮来获取尺寸,我们可以使用嵌入阴影来设置边框样式.

* {
  margin: 0; padding: 0; box-sizing: border-box;
}
button, input, wrapper {
  display: inline-block; border-radius: 3px;
}

.wrapper {
  position: relative;
  
  width: 60%;
  margin: 1em;
  background-color: #ccc;
}

input {
  border: 1px solid red;
  width: 100%;
  
  background-color: limegreen;
  line-height: 3em;
/*  padding: 0.75em; */
  padding: 10px;
}

button {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  border: 1px solid transparent;
  width: 7em;
  margin: 0px;
  background-clip: padding-box;
  box-shadow:  inset 0px 0px 0px 2px  black;
}
Run Code Online (Sandbox Code Playgroud)
<div class="wrapper">
  <input type="text">
  <button>Test</button>
</div>
Run Code Online (Sandbox Code Playgroud)

另一个例子,按钮边框.但是我们需要一个包装器才能使尺寸正常.

* {
  margin: 0; padding: 0; box-sizing: border-box;
}
button, input, wrapper {
  display: inline-block; border-radius: 3px;
}

.wrapper {
  position: relative;
  
  width: 60%;
  margin: 1em;
  background-color: #ccc;
}

input {
  border: 1px solid red;
  width: 100%;
  
  background-color: limegreen;
  line-height: 3em;
/*  padding: 0.75em; */
  padding: 10px;
}

.buttonwrap {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  border: 1px solid transparent;
  width: 7em;
  margin: 0px;
  background-clip: padding-box;
}
button {
  position: absolute;
  right: 0px;
  top: 0;
  bottom: 0;
  width: 100%;
  border: 2px solid blue;
  margin: 0px;
}
Run Code Online (Sandbox Code Playgroud)
<div class="wrapper">
  <input type="text">
  <div class="buttonwrap">
      <button>Test</button>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)