在Firefox中折叠边距对齐

时间:2014-01-23 04:04:23

标签: html css

TLDR:this codepen在Chrome中运行良好,但Firefox中的对齐功能已关闭。

我正在构建一个jQuery plugin,修改文本输入以在左侧为其提供一个下拉按钮。为了获得正确的定位,我添加了一个包装div,它与输入的高度相同,因此按钮可以绝对定位在输入的顶部,但仍然具有相同的高度:

#wrapper {
  position: relative;
}
#overlay {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 30px;
}

这样可以正常工作,直到输入有垂直边距:然后容器增长到包含边距,因此下拉按钮随之增长。我对此的解决方案是边缘折叠:我给出了输入显示:块,这意味着容器忽略了它的边距。一切都好。

input {
  margin: 20px 0 40px; /* testing */
  display: block;
}

但现在的问题是,默认情况下,输入是内联元素,例如您可能希望在输入旁边有一个提交按钮。所以我将整个东西包装在一个带有display:inline-block的容器div中,所以像按钮这样的另一个内联元素可以很好地坐在它旁边。

#container {
  display: inline-block;
}

这在Chrome中运行良好,但在输入上有任何垂直边距时,Firefox中会出现奇怪的对齐问题。下面我添加了最终标记。顶部还有一个codepen链接。

<div id="container">
  <div id="wrapper">
    <input>
    <div id="overlay"></div>
  </div>
</div>
<button>Submit</button>

编辑:关键是这是一个插件,我正在尝试使用用户现有的标记和CSS,例如他们有这个标记:

<input><button>Submit</button>

并且他们现有的CSS在输入上有垂直边距,我希望他们能够在输入上初始化我的插件,它只是工作,而不强迫他们改变他们的标记/ CSS。现在因为插件需要在输入周围添加大量标记(对于叠加层和下拉列表),我将它全部包装在容器div中。此容器div是我们的范围限制(并且不包括按钮元素,或者他们选择放在其输入旁边的任何其他内容)。

6 个答案:

答案 0 :(得分:2)

要解决此问题,您需要在父line-height中定义div#test2。没有它,different browsers will give it different values。这将导致Firefox导致这种奇怪的结果。

现在,line-height不是唯一的问题,vertical-align的基线值也会为内联元素生成不同的结果,而不是具有不同高度的内联块元素比周围的内联内容。要解决此问题,请将top元素的值更改为#container(因为那是inline-block元素。)

最终结果将更改以下内容(仅粘贴已更改的部分):

#test2 {
    background-color: green;
    line-height:70px;
    #container {
        // replicate the inline nature of the input
        display: inline-block;
        vertical-align:top;
    }
    //the rest of the #test2 nested code
}

这看起来像this

回复评论

我已经根据需求设置了一些功能。既然你说了额外的代码(所以输入周围的div)都是由插件本身做出的,我已经冒昧地改变它以使其工作。

它可以很容易地工作的方式就是根本不使用内联块,并坚持使用内联元素。这会将样式更改为以下内容:

#container {
    // replicate the inline nature of the input
    display: inline;
}
#wrapper {
    display: inline;
    position: relative;
}
input {
    // you'll want to make sure the typed text doesn't appear behind the overlay
    padding-left:35px;
}
#overlay {
    position: absolute;
    top: 0px;
    bottom: 0px;
    left: 1px;
    width: 30px;
    background-color: #00C2FF;
}

注意:

  • 我没有费心使覆盖层覆盖输入的整个高度,因为无论如何你的插件只会让它成为一面旗帜。要使其覆盖整个高度,只需在叠加层上设置负topbottom样式,等于输入上的计算填充顶部和填充底部(分别)。在这种情况下,您必须将它们更改为top:-5px;bottom:-5px;。 (您可以通过jQuery的$(input).css('padding-top')
  • 获取计算出的样式
  • 你实际上也可以从中删除整个#container,因为它现在唯一的样式是display:inline,它实际上并没有为整个事物添加任何东西。
  • 我在你的输入中添加了一个填充,因为否则你必须在叠加层后面输入,这很愚蠢。

答案 1 :(得分:1)

插件生成的HTML是否需要保持完全相同?我不确定我能弄清楚为什么第二个例子不起作用,但你似乎有太多的div元素。你可以做得更简单:

HTML

<div id="test1">
  <div id="wrapper">
    <input>
    <div id="overlay"></div>
    <button>submit</button>
  </div>
</div>

SCSS

input, button {
  border: 1px solid black;
  padding: 5px;
}

input {
  display: inline-block;
  padding-left: 35px;
}

#test1 {
  background-color: yellow;
  padding: 20px 0 40px 0;
  #wrapper {
    position: relative;
    #overlay {
      position: absolute;
      top: 1px;
      left: 1px;
      width: 30px;
      background-color: #00C2FF;
    }
  }
}

Codepen example

我已经删除了边距,而是在父节点上使用了填充,它实现了相同的功能。您还需要在输入字段中添加一些padding-left,以便输入的文字不会在叠加层div后面消失。

编辑:如果您无法更改标记:

SCSS:

#test2 {
  background-color: green;
  #container {
    // replicate the inline nature of the input
    display: inline-block;
    padding: 20px 0 40px 0;
  }
  #wrapper {
    // this is just here to be display:block and ignore the margin on the input
    display: block;
    position: relative;
  }
  input {
    // tell parent to ignore margin
    //display: block;
    margin: 0;
  }
  #overlay {
    position: absolute;
    top: 1px;
    bottom: 1px;
    left: 1px;
    width: 30px;
    background-color: #00C2FF;
  }
}

codepen demo

block字段中删除了margininput声明,并将间距移至#container元素的填充。

答案 2 :(得分:0)

免责声明”:首先我要说的是我没有找到导致Firefox出现问题的确切原因,但我确实想到了另一种可以做到的方法。

这在Firefox和Chrome中的工作方式只是使用与您#test1完全相同的HTML,但除此之外,还使用了CSS :before伪元素(而不是使用#container#wrapper)。我使用的代码是:

#test2 {
    background-color: green;
    position:relative;
    &:before {
        content:"";
        display:block;
        position:absolute;
        left:1px;
        top:1px;
        bottom:1px;
        margin:20px 0 40px 0;
        width:30px;
        background:#00C2FF;
    }
}

demo

这样做的方法是简单地将:before叠加层放置在与div之前完全相同的位置。正如您所看到的,我使用了大多数相同的样式,但我将它们放在:before伪类上。

答案 3 :(得分:0)

其他答案不知道为什么它不适用于Firefox。好吧,我认为Firefox有正确的行为,这是Chrome问题。

简而言之,您希望将输入与按钮对齐。但输入是在包装器内。然后,您可以使用vertical-align来控制包装器和按钮之间的垂直对齐,但不能控制输入和按钮之间的垂直对齐。

在这里,您可以看到包含不同vertical-align的屏幕截图:

Screenshot with different <code>vertical-align</code>

请参阅the code

如果要对齐输入和按钮(图像中的最后一个案例),则会出现问题,因为您可以使用vertical-align的任何关键字执行此操作。仅在输入的上边距和下边距相等的情况下,vertical-align: middle才有效。

但总的来说,您还有另一种解决方案:vertical-align也接受<length>值。

而且,为了获得完美的对齐方式,您应该使用公式

vertical-align: -(input bottom margin)

或者,如果你想要对齐它们,即使按钮有一个底部边距,那么

vertical-align: -(input bottom margin) + (button button margin)

上面的代码公式适用于inline-block <div>,但不适用于<buttons>

公式必须固定为

vertical-align: -(input bottom margin) -(input offsetHeight)/2 + 6

在你的例子中

  • (输入底部边距)= 40px
  • (输入offsetHeight)= 31px

然后,你需要

vertical-align: -(input bottom margin) -(input offsetHeight)/2 + 6

Demo

答案 4 :(得分:0)

我可以通过以下方式实现它。Codepen 您必须知道应用于输入的CSS并将其应用于按钮

  button{
   position:absolute;
   margin-left:5px;
  }
  input, button {
   display: inline-block;
   margin: 20px 0 40px 0;
  }

答案 5 :(得分:-1)

请在您的代码中进行更新。

input, button {
    border: 1px solid #000000;
    margin: 20px 0 40px;
    padding: 5px;
    vertical-align: top;
}

希望它能运作

http://codepen.io/anon/pen/Isycu