垂直外边距合并的问题
外边距合并出现的三个场景
- 同一个BFC,且同处于普通流中的垂直相邻元素外边距合并
- 父子元素的外边距合并
- 空元素的外边距合并
合并规则
- 两个margin都是正值的时候,取两者的最大值;
- 当 margin 都是负值的时候,取的是其中绝对值较大的,然后,从0位置,负向位移;
- 当有正有负的时候,先取出负 margin 中绝对值中最大的,然后,和正 margin 值中最大的 margin 相加。
- 所有毗邻的margin要一起参与运算,不能分步进行
不让相邻元素外边距合并的方法
- 被非空内容、padding、border 或 clear 分隔开
- 不在一个普通流中或一个BFC中
- margin在垂直方向上不毗邻
- 如果我们想减少这种情况的发生:在实际编写过程中,应尽量避免同时使用
margin-bottom
和margin-top
<style type="text/css">
*{
padding: 0;
margin: 0;
}
.clearfix:after {
content: " ";
display: table;
clear: both;
}
.parent {
/* 对于这种父子外边距合并的情况,除了了让父元素形成BFC,给其加 padding 或 border 都可以 */
margin-top: 50px;
/*border: 1px solid red;*/
/*padding: 1px 0;*/
background-color: teal;
/*overflow: hidden;*/
}
.parent > div {
width: 100px;
height: 100px;
}
.child1 {
clear: right;
margin-top: 50px;
margin-bottom: 50px;
background-color: lightblue;
}
.child2 {
margin-top: 50px;
background-color: lightcoral;
opacity: 0.8;
}
</style>
</head>
<body>
<div class="parent">
<div class="child1"></div>
<!-- 添加内容 -->
<div class="child2"></div>
</div>
</body>
总结
- 这些 margin 都处于普通流中,并在同一个BFC中;
- 这些 margin 没有被非空内容、padding、border 或 clear 分隔开;
- 这些 margin 在垂直方向上是毗邻的,包括以下几种情况:
- 一个 box 的 top margin 与第一个子box 的 top margin
- 一个 box 的 bottom margin 与最后一个子box 的 bottom margin,但须在该box 的 height 为 auto 的情况下
- 一个 box 的 bottom margin 与紧接着的下一个 box 的 top margin
- 一个 box 的 top margin 与其自身的 bottom margin,但须满足没创建BFC、零min-height、零或者“auto”的 height、没有普通流的子元素
- 例外的情况:
- 根元素(html)的外边距不会参与折叠
- 设置任何属性的空span和空div不影响任何布局,可以无视之。
margin负值
表现
- 虽然margin可以应用到所有元素,但display属性不同时,表现也不同
- block元素可以使用四个方向的margin值
- inline元素使用上下方向的margin值无效
- inline-block使用上下方向的margin负值看上去无效:这与其默认的
vertical-align: baseline;
有关系,当垂直对齐的属性值为其它值时,则会显示不同的视觉效果
重叠
- margin负值并不总是后面元素覆盖前面元素,它与元素display属性有关系
- 两个block元素重叠时,后面元素可以覆盖前面元素的背景,但无法覆盖其内容
- 当两个inline元素,或两个line-block元素,或inline与inline-block元素重叠时,后面元素可以覆盖前面元素的背景和内容
- 当inline元素与block元素重叠时,inline的元素覆盖block元素的背景和内容
- 当inline-block元素与block元素重叠时,inline-block元素覆盖block元素的背景,但无法覆盖其内容
浮动
- block元素与浮动元素重叠时,其边框和背景在该浮动元素之下显示,而内容在浮动元素之上显示
- inline或inline-block元素与浮动元素重叠时,其边框、背景和内容都在该浮动元素之上显示
定位
- 定位元素(position不为static)覆盖其他元素的背景和内容
- 将relative属性值应用于inline元素,由于无法改变其行内元素的本质,所以其上下margin依然存在问题
应用
- 水平垂直居中:由于margin的百分比相对于包含块的宽度,所以在需要居中的元素外面套一个空的
<div>
元素,并且利用absolute
的包裹性,使该元素的宽高等于需要定位的元素的宽高
<style type="text/css">
.box{
position:relative;
width: 200px;
height: 200px;
border: 2px solid black;
background-color: lightgreen;
}
.out{
position: absolute;
left: 50%;
top: 50%;
}
.in{
height: 100px;
width: 100px;
margin-left: -50%;
margin-top: -50%;
background-color: pink;
}
</style>
</head>
<body>
<div class="box">
<div class="out">
<div class="in">测试内容</div>
</div>
</div>
</body>
- 列表项两端对齐:在列表项外面包一层元素,使用margin负值来将最后一个列表项拉回来
<style type="text/css">
ul{
margin: 0;
padding: 0;
list-style:none;
}
.box{
width: 200px;
background-color: pink;
}
.list{
overflow: hidden;
margin-right: -10px;
}
.in{
float: left;
width: 60px;
height: 100px;
margin-right: 10px;
background-color: lightgreen;
}
</style>
</head>
<body>
<div class="box">
<ul class="list">
<li class="in">1</li>
<li class="in">2</li>
<li class="in">3</li>
</ul>
</div>
</body>
- 三栏自适应布局:中间的主体使用双层标签,外层
<div>
宽度100%显示,并且浮动,内层<div>
为真正的主体内容,含有左右210px的margin值。左栏和右栏都采用margin负值。左栏左浮动,margin-left为-100%,正好使左栏位于页面左侧。右栏左浮动,大小为其本身的宽度200px
<style type="text/css">
html,body{
height: 100%;
}
body{
margin: 0;
}
.main{
float: left;
width: 100%;
height: 100%;
}
.main .in{
height: 100%;
margin: 0 210px;
background-color: pink;
}
.left,.right{
float: left;
width: 200px;
height: 100%;
background-color: lightgreen;
}
.left{
margin-left: -100%;
}
.right{
margin-left: -200px;
}
</style>
</head>
<body>
<div class="main">
<div class="in">in</div>
</div>
<div class="left">left</div>
<div class="right">right</div>
</body>
- 三栏等高布局:给每栏设置大的底部内边距,然后用数值相同的负外边距消除这个高度,然后在外层容器中设置
overflow: hidden;
<style type="text/css">
body{
overflow: hidden;
margin: 0;
}
ul{
margin: 0;
padding: 0;
list-style: none;
}
.list{
overflow: hidden;
width: 100%;
height: 100%;
}
.main{
margin: 0 210px;
background-color: lightgreen;
}
.left{
float: left;
width: 200px;
background-color: pink;
}
.right{
float: right;
width: 200px;
background-color: pink;
}
.main,.left,.right{
margin-bottom: -9999px;
padding-bottom: 9999px;
}
</style>
</head>
<body>
<ul class="list">
<li class="left">左侧文字比较少</li>
<li class="right">右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多右侧文字比较多</li>
<li class="main">中间文字比较少</li>
</ul>
</body>