发表于: 2020-02-28 23:51:27

1 656


一、背景介绍

CSS盒模型中,margin是我们非常熟悉的一个属性,大多数情况下,我们采用的都是正数的 margin 值,可能有时候会用到负的 margin 值。在我们的印象中,负的 margin 值就类似于浏览器的 hack 一样,不被人接受。但是,本文要说明的就是,负的 margin 值并不是 hack,这是正常范围内的写法。

根据 W3C,margin 是能够接受负值的,只是在具体实现上有一些区别。那么,设置margin为负值究竟会是什么样的效果呢?


二、知识剖析

MARGIN为负值时产生的影响

1、对文档流的影响

当非浮动、非定位元素的margin-top/margin-left被赋予负值时,元素将被拉进指定的方向。

但这种偏移不同于相对定位,通过相对定位偏移后,其仍然会坚守着它原来占据的空间,不会让文档流的其它元素乘虚而入。而通过负边距进行偏移的元素,它会放弃偏移前占据的空间,这样它后面文档流中的其它元素就会“流”过来填充这部分空间。

但如果你设置margin-bottom/right为负数,元素并不会如你所想的那样向下/右移动,而是将后续的元素拖拉进来,覆盖本来的元素。

文档流只能是后面的流向前面的,即文档流只能向左或向上流动,不能向下或向右移动。

所以,一切只要是由文档流决定的东西,负边距就能起作用了。

2.左和右的负边距对元素宽度的影响

负边距不仅能影响元素在文档流中的位置,还能增加元素的宽度!

如果没有设定width属性,设定负margin-left/right会将元素拖向对应的方向,并增加宽度,此时的margin的作用就像padding一样。

总结,在文档流中,元素的最终边界是由margin决定的,margin为负的时候就相当于元素的边界向里收,文档流认的只是这个边界,不会管你实际的尺寸是多少。

3、对浮动元素的影响

负边距对浮动元素的影响与负边距对文档流中元素的影响其实是差不多的。文档流中元素的位置由文档流的走向决定,浮动的元素也可以看成有一个“浮动流”存在,不过浮动流既可以向左,也可以向右。

负margin会改变浮动元素的显示位置,即使元素写在DOM的后面,也能让它显示在最前面。圣杯布局、双飞翼布局啊什么的,都是利用这个原理实现的。

就是某个元素虽然是写在了后面,但可以通过负边距让它在浏览器显示的时候是在前面的

4、对绝对定位的影响

绝对定位的元素定义的top、right、bottom、left等值是元素自身的边界到最近的已定位的祖先元素的距离,这个元素自身的边界指的就是margin定义的边界,所以,如果margin为正的时候,那它的边界是向外扩的,如果margin为负的时候,则它的边界是向里收的。

可以通过这个特性来利用绝对定位居中,但该方法的缺点是必须要知道要居中元素的高度和宽度。


三、常见问题

MARGIN负值在页面布局中有哪些应用?


四、解决方案

1.负边距+定位:水平垂直居中

使用绝对定位将content的定点定位到body的中心,然后使用负margin(content宽高的一半),将content的中心拉回到body的中心,已到达水平垂直居中的效果。

2.去除列表右边距

我们使用浮动列表展示信息的时候,为了美观通常为每个列表之间设置一定的间距(margin-right),当父元素的宽度固定时,每一行的最右端的li元素的右边距就多余了,去除的方法通常是为最右端的li添加class,设置margin-right:0; 这种方法需要动态判断为哪些li元素添加class,比较麻烦。

3.去除列表最后一个li元素的border-bottom

列表中我们经常会添加border-bottom值,最后一个li的border-bottom往往会与外边框重合,视觉上不雅观,往往要移除。

我们可以为li元素设置margin-bottom:-1px;来实现,不过不要为ul/ol设置高度,需要高度请在外层嵌套一个div设置高度。

4.负边距自适应布局

此例适用于一栏宽度固定一栏宽度自适应的布局,就像QQmail一样,导航栏宽度固定,内容区域随着浏览器的大小而自动缩放。

大家自然想到使用百分比来定元素的宽度,可是浏览器无法理解100%-200px这样的表达式。这里我们就需要元素嵌套和负边距的思想。

5.google reader自适应渐变圆角按钮

现在大家都比较追求纯,前端人士追求的是纯css,无图片,自适应。google reader 的按钮就具备了以上特点,而且还有渐变的效果,其内层div的左右border就使用了负边距以达到模拟1像素圆角的效果,

6.三栏等高

关键是给每个框设置大的底部内边距,然后用数值相似的负外边距消除这个高度。这会导致每一列溢出容器元素,如果把外包容器的overflow属性设为hidden,列就在最高点被裁切。


五、编码实战


六、拓展思考

MARGIN负值是否会改变元素的宽度?

这取决于是否给了元素宽度,如果已经给了元素宽度,那么margin负值不会影响元素的宽度,如果没有给元素宽度,那么margin会影响元素的宽度.




返回列表 返回列表
评论

    分享到