同早年~


问题描述

在xx项目中,羊城通卡号的输入框处使用了xx库中的实现方式,即将提示文字标签<label>通过负margin移位到<input>框的下面。静态时展现良好,js逻辑添加后发现,输入文字时<input>框会抖动。排查后发现,是重置了<label>的负margin值引起的。这引起了我对负margin定位的兴趣,于是乎,做了个简单的测试。

负margin的移位参考线-LMLPHP

Demo测试

初始状态:

负margin的移位参考线-LMLPHP

图 (1)

负margin的移位参考线-LMLPHP

灰框 {margin-bottom:-10px;}:

负margin的移位参考线-LMLPHP

图 (2)

灰框 {margin-bottom:-30px;}:

负margin的移位参考线-LMLPHP

图 (3)

绿框 {margin-top:-10px;}:

负margin的移位参考线-LMLPHP

图 (4)

绿框 {margin-top:-30px;}:

负margin的移位参考线-LMLPHP

图 (5)

灰框 {margin-top:-30px;}:

负margin的移位参考线-LMLPHP

图 (6)

以上可以看出:

  • 元素的margin-bottom为负值时,元素本身不动,其下的元素上移(图2、3)。
  • 元素的margin-top为负值时,元素上移,其下的元素也跟着上移(图4、5、6)。
  • 上下紧邻的两个元素,设置上面元素的margin-bottom与设置下面元素的margin-top,视觉效果相同(图2与4、3与5的比较)。

让灰框和绿框都左浮,下面添加一没有清浮的段落,再来测一组:

初始状态:

负margin的移位参考线-LMLPHP

图 (1)

负margin的移位参考线-LMLPHP

绿框 {margin-bottom:-29px;}:

负margin的移位参考线-LMLPHP

图 (2)

绿框 {margin-bottom:-30px;}:

负margin的移位参考线-LMLPHP

图 (3)

从上一组测试的图2、3,以及这组数据可以很形象地看出,当元素的margin-bottom设为负的x像素时,就好像这个元素释放出了下方x像素的空间,当x等于该元素的高度时,空间完全被释放,其它元素就当该元素不存在似的。故本组图2中的”text”还卡在绿框的右边,而图三中(负margin-bottom值等于元素高度)”text”“穿”过绿框,直接卡到了灰框的右侧。

水平方向的大致类似,即元素的margin-right为负值时,元素本身不动,右侧的元素左移,元素的margin-left为负值时,元素左移,右侧的元素也跟着左移。

问题分析

了解了负margin尤其是负margin-bottom的定位原则,再来看前面提到的抖动问题:

负margin的移位参考线-LMLPHP

因为<input>框中输入文字时,提示文字是要消失的(<label>标签{display:none;}),故<label>的负margin-bottom值要与<label>的高度一致。否则若值过大(如-31px),输入文字时<input>框会向下抖动,若值过小(如-29px),则输入文字时<input>框会向上抖动。知道了这些,也就不难理解库中为什么通过设置<label>的负margin-bottom,而不是通过设置<input>的负margin-top来实现两个元素的叠加效果了。

2012.12.8

05-02 05:23