21

目的:

我正在编写与此类似的代码来创建一个输入字段具有嵌入式按钮的组件

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

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

还要注意的是,文本输入的边框必须保持可见并包裹按钮。为了实现这一点,我margin: 1px按钮上添加了一个(应该)空间来显示周围的文本输入红色边框(通常在输入字段内容无效时)。

问题:

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

CSS 看起来不错,但它似乎是渲染中的计算/舍入问题,按钮的底部或顶部边距并不是真正的 1px(可以看到它检查元素)。而且输入的填充似乎也有影响。

在不同的缩放率下,它会在button的顶部或底部添加或删除 1px 的边距,从而产生 1px-gap 或覆盖边框

当我将按钮边距设置为时0px,底部边距是固定的,但我在顶部松开了 1px 边距,最终覆盖了text-input的红色边框。

示例:

可能我解释不清楚或过于冗长,所以这里有一些错误的截图,来自 Chrome 上的不同缩放(注意 CSS 总是相同的):

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

解决方案:

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

4

2 回答 2

15

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

例如,在 Chrome 中,边框可以具有小数大小,但边距的处理方式不同(作为整数)。

我没有来自 Chrome 团队的文档,但可以在开发工具中看到:

开发工具捕获

AFAIK,没有办法改变它。

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

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

剩下的窍门就是把 background-clip 属性设置为 padding box,这样这个透明度就不会受到背景的影响

Chrome 中还有一个错误,当浏览器缩放时,以 em 表示的填充在这种精度级别上是不可靠的。我在片段中更改了它。

由于我们使用边框按钮来确定尺寸,因此我们可以使用嵌入阴影来设置边框样式。

* {
  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;
}
<div class="wrapper">
  <input type="text">
  <button>Test</button>
</div>

另一个例子,按钮边框。但是我们需要一个包装器来确定尺寸。

* {
  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;
}
<div class="wrapper">
  <input type="text">
  <div class="buttonwrap">
      <button>Test</button>
  </div>
</div>

于 2016-01-12T16:42:20.917 回答
-1

使用http://autoprefixer.github.io/获取显示所需的跨浏览器支持: flex;

button, input, wrapper {
  display: inline-block; <----- Remove "display: inline-block;"
  border-radius: 3px;
}

.wrapper {
  position: relative;
  display: -webkit-box;<----- Add "display: flex;"
  display: -webkit-flex;<----- Add "display: flex;"
  display: -ms-flexbox;<----- Add "display: flex;"
  display: flex;<----- Add "display: flex;"
  width: 60%;
  margin: 1em;
  background-color: #ccc;
}

额外的阅读和学习材料:

https://css-tricks.com/snippets/css/a-guide-to-flexbox/

http://flexbox.io/#/

https://philipwalton.github.io/solved-by-flexbox/demos/holy-grail/

http://www.sketchingwithcss.com/samplechapter/cheatsheet.html

注意:要覆盖 flex 规则,您需要使用 flex 简写而不是特定的覆盖,因为当前浏览器存在缺陷,例如。

.item {
  flex: 0 0 300px;
}

/* overide for some reason */

.item {
  flex: 1 0 300px;
}

/* NOT */

.item {
  flex-grow: 1;
}

您可能需要对 ie11 进行覆盖:

.ie11std .wrapper {
  display:table;
}

.ie11std .item {
  display:table-cell;
}

虽然这不会响应。

于 2016-01-17T01:58:33.233 回答