关于margin对于一个前端开发者是很是常见的一个CSS属性,而我今天所分享margin属性是为了更加深刻的了解margin的一些特性,从而在实际应用中,减小代码量。主要内容以下:css
1.关于margin的百分比特性。前端
2.关于margin的auto的做用机制。css3
3.关于margin的重叠。浏览器
4.关于margin的负值。布局
1、margin的百分比特性。spa
咱们使用百分比时常常会忽略这个问题,margin的百分比相对于咱们直接设置margin-top这类有所不一样,margin的百分比是相对于容器水平宽度来计算的。这里有两种状况:设计
1.做用元素为普通元素(float\position等均不是普通block元素)3d
在这种状况下,百分比是相对于父元素的宽度计算。如:blog
<div style="width: 300px; height: 100px;">图片
<div style="width: 100px; height: 40px; margin: 10%;display: inline-block;"></div>
</div>
(注意:为何这里我要用inline-block呢。)
此时margin值为父元素宽度的10%,也就是margin-top为30px,margin-left为30px。
2.做用元素为绝对定位元素
在这种状况下,百分比是相对于祖先元素或者最近的定位父元素宽度计算的。如:
<div style="width: 800px; height: 150px; ">
<div style="width: 300px; height: 100px; margin-left: 100px; ">
<div style="width: 100px; height: 40px; margin: 10%; position: absolute;"></div>
</div></div>
此时由于div使用了position,因此margin值是根据祖先元素的宽度进行计算。
2、margin的auto的做用机制。
关于margin的auto可能你们在熟悉不过了,用的最多的可能就是margin:0 auto;来进行水平居中定位了,可是你真的了解它是怎么实现的吗?是否你也遇到过img图片没法使用这个水平居中和margin:auto 0 没法进行垂直居中呢?接下来带着疑问,我将分享我理解的auto机制。
我用比较通俗的方式表达margin:auto的机制,即是为了填充由于强制变动尺寸而设计的属性。
举一个例子:
第一个例子是在一个div中,加入了一个没有设定宽度的p标签,众所周知p标签是一个块级元素,而浏览器默认为水平流布局,因此p标签水平独占一行,而后咱们对比第二个例子,是设定了强制设定宽度100px的p标签但依旧独占一行,而后对比第三个例子,是强制设定了宽度100px而且margin-right:100px,margin-left:auto的p标签。此时margin-left:auto既是左边剩余空间大小。这样咱们就很好理解为何margin:0 auto能使元素水平居中了。是由于它至关于margin-left:auto;margin-right:auto;即直接把剩余空间平分给两侧处理。可能你们都常用第三个列子中没有添加auto时,margin-right始终不能执行,如今能够知道它的原理了吧。下次就可使用它了。
理解了上面的机制后,咱们看看为何img使用上面的方法依旧不行呢。如今应该不少朋友都知道了,由于img是inline水平,及时你使用margin:0 auto;可是它没有须要处理的剩余空间,因此依旧没法实现居中,这个时候咱们只要让它变成block元素,效果就天然呈现了。
解决了第一个问题,如今咱们解决第二个问题,咱们是否能用margin:auto 0来实现垂直居中呢?答案是:固然能够得!
在前面咱们讲到浏览器是默认为水平流布局,及块级元素是会自动填充满一整行的。而咱们的auto是处理被更改的剩余空间的,而咱们的高度方向并非自动充满一整行,因此即便你强制设定了高度,可是依旧没有的剩余空间,没有剩余空间auto天然不会作出反应。可能小伙伴们已经知道如何解决这一个问题了,既是把水平流布局更改成垂直流布局。改变布局后,垂直方向便可自动填充一列,writing-mode:vertical-lr;是css3中的属性,即改变此元素的布局为垂直流布局。这样,一个垂直居中及完成了。
有小伙伴要问了,如今垂直居中了,可是水平又不能居中了。如今即刻分享水平垂直方向都居中的办法(办法有不少,此处是根据margin和绝对定位来实现的)。
代码先行:
<div style="width: 500px; height: 300px; position: relative;">
<div style=" width: 100px; margin: auto; height: 100px; position: absolute; top: 0; right: 0; left: 0; bottom: 0" ></div>
</div>
细化分析,咱们给img元素一个绝对定位,而后给它top/left/bottom/right都设置为0,此时里面div元素填充满整个外层div,而后咱们强制改变了他的宽度很高度,此时它便有了剩余空间,根据上面的机制,auto处理了剩余空间,及让它水平垂直都成功居中。
3、margin的重叠概念
关于margin的重叠咱们在实战中常常会出现,下面举例一个简单的例子:
*{ margin: 0; padding: 0; }
p{line-height: 1em; margin: 1em 0;}
<p style="">1</p>
<p style="">2</p>
这种例子在实际中很常出现,但到底有什么端倪呢。当你在浏览器上显示出这段代码的时候,你会发现,在咱们常理判断下,俩个p标签都有margin,应该之间的距离有两个p标签的高度啊,但咱们能从肉眼发现,彻底没有。这就是margin的重叠机制。
可是这是有前提条件的:
1.必须为block水平元素(不包括float和absolute元素);
2.不考虑writing-mode,只发生在垂直方向;
margin重叠一般出如今三种情形下
第一种:既是上面举例的相邻两个兄弟元素
第二种:父元素和第一个或者最后一个子元素
第三种:空的block元素;
第一种咱们已经举例说明,如今说第二种,父元素和第一个子元素的重叠。咱们仍是先写出代码块:
<div style="width: 200px; height: 200px; ">
<div style="margin-top: 100px;">1</div>
</div>
这也是咱们常常碰见的问题,咱们想要的结果是子元素与父元素的距离为100px,可是咱们设置后发现,是父元素和浏览器出现了top值,这即是margin重叠的神奇,这就等同于父元素设置了top值,但有时候咱们会以为这样达不到想要的效果,其实,咱们只须要在父元素加入overflow: hidden; 即可以清除重叠机制;父子元素重叠依旧有不少条件,下面我把列举出来,你们能够试试。
margin-top重叠条件:
1.父元素费块状格式化上下文元素
2.父元素没有border-top和padding-top值
3.父元素和第一子元素没有inline元素分隔
margin-bottom重叠条件:
1.父元素费块状格式化上下文元素
2.父元素没有border-bottom和padding-bottom值
3.父元素和最后一个元素没有inline元素分隔
4.父元素没有height相关的限制;
其实这些条件也是咱们消除父子元素重叠的方式。
第三种空的block元素,下面是例子:
<div style=" overflow: hidden;">
<div style="margin: 1em 0;"></div>
</div>
里面的div设置了margin-top:1em,margin-bottom:1em,按照常理,外面容器应该被撑大到2em,可是实际上却依旧是1em;以上即是margin重叠的三种状况。它是一把双刃剑,因此咱们须要合理利用它的重叠。
4、margin的负值
利用margin的负值在咱们实战中是很是有效的一个技能。咱们一般会遇到这么一个布局,三个或者多个div在同一行的显示的时候须要咱们作出这样的效果(这样的效果有不少方法作到,这里只讨论margin实现):
在我刚入门的时候,我老是统一个div一个共有的margin值,获得以下效果:
而后再利用JS或者固定class属性来控制每一行最后一个div的margin值为0。不知道是否有朋友和我同样这样作,这确实不算一个有用的办法。而margin负值改变了这一切,让咱们并不须要去单独处理某一div。
.box{width: 320px; height: 200px; overflow: hidden;}
.box>div>div{width: 100px; height: 100px; background-color: royalblue; float: left;margin-right: 10px;}
.box>div{margin-right: -10px;}
<div class="box">
<div>
<div>1</div>
<div>2</div>
<div>3</div>
</div>
</div>
根据上面的代码,咱们轻易的达到了咱们想要的效果,如今咱们再分析,这是如何作到的。在分析以前,咱们要了解margin有一个很实用的技能,即是改变可视尺寸(前提条件:无高宽的普通block元素和只针对水平方向)。这个技能即是咱们实现这个效果的重点。简单的说,在没有设置宽高的时候,咱们div元素的宽度是外层容器的宽度,当咱们给div一个margin-left:100px时,div元素相距左边有100px,而咱们div元素的宽度就变成了外层容器宽度减去100px;同理,当咱们给div设置了margin-right:-10px的时候,至关于容器就在原来的基础上向右边多出来10个像素,而这10个像素正好是咱们margin须要的空间,天然咱们要排列的div就不会跑到下一行里去了,而在最外层设置overflow:hidden;是为了也不影响咱们外面的全部布局。可能只从文字上仍是比较难以理解,因此代码还须要本身实际操做才能让它深刻你心。
关于margin负值可不仅是这么一点用处,下面咱们将分析一个关于margin-bottom负值所带来的经典案例:等高布局。
咱们一般但愿,无论左边内容和右边内容是否一致,可是他们最终外面的容器高度都但愿一直。不少小伙伴通常状况是使用固定高度来解决这么一个问题,可是有时候咱们并不知道咱们其中的内容究竟是多少毕竟大多数时候都是后台来生成这个内容的,那固定高度的办法当然就失败了。这时候,就该咱们margin-bottom出击了。
<style>
*{ margin: 0; padding: 0; list-style: none;}
.red,.green{float: left; width: 300px; margin-bottom: -600px; padding-bottom: 600px;}
.red{}
.green{background-color: green;}
.content{ overflow: hidden;}
</style>
<body>
<div class="content">
<div class="red">
<ul>
<li>1</li>
</ul>
</div>
<div class="green">
<ul>
<li>1</li>
<li>2</li>
<li>2</li>
</ul>
</div>
</div>
效果以下:
不论你两边内容是否一致,已经等高,首先咱们给咱们内容div给出一个足够大的margin-bottom负值,而后再使用padding撑开这个div,此时这个div大小足以让咱们放入足够多的列表。(注:在我理解看来,其实也是设置一个高度,只是这个高度并不像直接设置出来的高度那样直接显示出来暂具空间,而是根据内容慢慢显示出来,overflow:hidden就是拿来隐藏没有使用的空间高度)。
不知道你读完后是否以为咱们经常使用的margin也这么神奇呢?又或许其实上面的效果你能够用不少方法来代替它,这或许不是最优解,可是多一种方法会让咱们多一种思路。如如有错的地方,但愿你们指出。