BFC的学习
BFC全称Block Formatting Context,即块级格式化上下文(IFC:内联元素格式化上下文),BFC是一个独立的布局环境,在这个环境里面物品的摆放是不受外界的影响的。转换为BFC的理解则是:BFC中的元素的布局是不受外界的影响(可以利用这个特性来消除浮动元素对其非浮动的兄弟元素和其子元素带来的影响。),在一个BFC中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直的沿着其父元素的边框排列。
BFC布局规则:
内部box在垂直方向,一个一个排列
box在 BFC 垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
BFC 区域不会与 浮动区域重叠
BFC 在页面上是一个独立的容器,与其他元素互不影响
计算 BFC 高度时,浮动元素也会参与计算
BFC触发(创建)条件
满足其中一个就可以触发
float的值不为none
overflow的值不为visible
display的值不为默认
position的值为absolute或fixed
BFC的应用
a.自适应两栏布局
<style type="text/css">
.left{
width: 300px;
height: 300px;
background-color: yellowgreen;
float: left;
}
.right{
height: 300px;
background-color: yellow;
}
</style>
b.防止垂直margin重叠
<style type="text/css">
.warp {
overflow: hidden;
}
p {
color: #f55;
background: #fcc;
width: 200px;
line-height: 100px;
text-align: center;
margin: 100px;
}
</style>
</head>
<body>
<p>哎哎哎</p>
<div class="warp">
<!--在p外面包裹一层div,出发了BFC,那么两个p就不属于同一个BFC,不会出现margin重叠-->
<p>dddd</p>
</div>
</body>
c.清除浮动
①:overflow:hidden | auto
②:父级元素也一起浮动(不推荐使用)
③:父元素设置display:table,子元素设置display:table:cell(不推荐使用)
flex的相关知识(主要是弹性盒模型)
1.Flexible boxes盒子
盒子按照宽高分出了以下8点
注意:设置为flex布局后,子元素的float、clear和vertical-align属性将失效。
2.属性设置
① flex-direction:主轴的方向(即项目的排列方向)
属性值:row(默认值) 主轴为水平方向,起点在左端。
row-reverse 主轴为水平方向,起点在右端。
column 主轴为垂直方向,起点在上沿。
column-reverse 主轴为垂直方向,起点在下沿。
②flex-wrap:控制flex容器是单行或者多行,同时横轴的方向决定了新行堆叠的方向。
属性值:nowrap(默认):不换行。
wrap:换行,第一行在上方。
wrap-reverse:换行,第一行在下方。
③flex-flow:flex-direction属性和flex-wrap属性的简写
④justify-content :定义了项目在主轴上的对齐方式
它可能取5个值,具体对齐方式与轴的方向有关。下面假设主轴为从左到右。
属性值: flex-start(默认值) 左对齐
flex-end 右对齐
center 居中
space-between 两端对齐,项目之间的间隔都相等。
space-around 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
<style type="text/css">
.box{
width: 1000px;
height: 300px;
background-color: blue;
display:flex;
flex-direction:row-reverse;
justify-content:space-around;
}
.div1,.div2,.div3,.div4{
width: 150px;
height: 130px;
background-color: yellow;
}
</style>
<div class="box">
<div class="div1">ttt</div>
<div class="div2">eee</div>
<div class="div3">xxx</div>
<div class="div4">ttt</div>
</div>
⑤align-items:定义项目在交叉轴上如何对齐
它可能取5个值。具体的对齐方式与交叉轴的方向有关,下面假设交叉轴从上到下。
属性值:flex-start 交叉轴的起点对齐。
flex-end 交叉轴的终点对齐。
center 交叉轴的中点对齐。
baseline 项目的第一行文字的基线对齐。
stretch(默认值) 如果项目未设置高度或设为auto,将占满整个容器的高度。
<style type="text/css">
.box{
width: 1000px;
height: 300px;
background-color: blue;
display:flex;
align-items: baseline;
}
.div1,.div2,.div3,.div4{
width: 150px;
height: 130px;
background-color: yellow;
}
</style>
⑥align-content:多根轴线的对齐方式,一根轴该属性无效
属性值:flex-start 与交叉轴的起点对齐。
flex-end 与交叉轴的终点对齐。
center 与交叉轴的中点对齐。
space-between 与交叉轴两端对齐,轴线之间的间隔平均分布。
space-around 每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
stretch(默认值) 轴线占满整个交叉轴。
⑦设置在项目上的6个属性
order:项目的排列顺序。数值越小,排列越靠前,默认为0
flex-grow:放大比例,默认为0-如果存在剩余空间也不放大。
—-如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。
—-如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
flex-shrink:缩小比例,默认为1-如果空间不足项目将缩小。
—-如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。
—-如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。
—-负值对该属性无效。
flex-basis:在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小
—-如果设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。
—-flex-basis:flex-basis可以理解为我们给子元素设置的宽度。
—-默认值是auto,宽度设置为auto时,盒子的宽度取决你们元素的宽度。
flex:flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。
—-该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。
—-建议优先使用这个属性而不分开写,浏览器会推算相关值。
—-grow表示伸张因子,shrink表示是收缩因子。
—-grow在flex容器下的子元素的宽度之和比容器小的时候起作用。
—-grow定义了子元素的宽度增长因子,除去子元素之和剩下的宽度会按照各个子元素的gorw值进行平分加大各个子元素上。
—-计算容器还剩空间:available_space(容器还剩的空间)=container_size(容器宽度)-flex_item_total(子元素宽度之和)
—-计算增长单位:grow_unit(增长单位)=available_space/flex_grow_total(子元素增长因子之和)
—-得到子元素的宽度:flex-item-width(子元素计算得到的宽度)=flex-basis+grow-unit*flex-grow
align-self:允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。该属性可能取6个值,除了auto,其他都与align-items属性完全一致。
display属性
inline—————-行内元素
block—————-块元素
inline-block———行内块元素
table—————-以表格形式显示,类似于table元素
table-row———–以表格形式显示,类似于tr元素
table-cell———–以表格单元格形式显示,类似于td元素
none—————-隐藏元素
display:block
容器类型的元素基本都是这个值。除 div之外,还有 h1到 h6,p, form, header, footer, section, article默认值。
display:none
像行内元素类型一样显示,可以隐藏某个元素,且隐藏的元素不会占用任何空间。也就是说,该元素不但被隐藏了,而且该元素原本占用的空间也会从页面布局中消失。
display:none和visibility:hidden的区别:
display:none:隐藏对应元素,在文档的布局中不再给他分配空间,而它的各边元素会合拢,当他没有存在过
visibility:hidden:隐藏对应元素,但在文档布局中依然保留原来的空间
display:inline-block(内联块)
inline-block将元素转换为行内块元素,具有以下特点:
1.可以定义width和height
2.可以与其他行内元素位于同一行。
既具备块元素的特点,也具备行内元素的特点,在html中,常见的inline-block元素有两个:img元素和input元素,对于这两个inline-block元素,一定要牢记于心。
demo
<style type="text/css">
span{
width: 50px;
height: 100px;
background-color: #ff5555;
display: inline-block;
}
</style>
</head>
<body>
<span>111</span>
<span>222</span>
<span>333</span>
</body>
从上面的结果图中可以看到span之间会有间隙,出现间隙的情况时使用maigin负值、移除空格、使用font-size:0、letter-spacing、word-spacing或者span不换行
display:inline
可以与其他行内元素位于同一行
行内元素内部可以容纳其他行内元素,但是不可以容纳块元素。
无法定义高度(height)和宽度(width)。
可以定义margin-left和margin-right,无法定义margin-top和margin-bottom
属性值:inline:和其他元素都在一行上,对于左右外边距和填充,顶和底边距不可改变
不能设置宽高,宽由元素撑开
允许其他元素在左右两边
block:总是重新起一行,高度、行高、顶以及底边距都可控制
inline-block:将对象作为内联对象,而对象的内容作为块对象,旁边的内联对象可以出现在同一行,允许出现空格
既可以像块元素一样定义宽高,又可以像内联元素排列在一行
display:table-cell
display:table-cell可以让元素以表格单元格的形式呈现,也就是说table-cell类型的元素具备td元素的特点。
实现功能:
(1) 图片垂直居中与元素
(2)自适应等高布局
(3)自动平均划分元素,并且在一行显示。
demo:(1) 图片垂直居中与元素 :
用“display:table-cell”和“vertical-align:middle”来实现大小不固定的图片的垂直居中效果,但是图片的width和height都必须小于表格的width和height的大小。
<style type="text/css">
div{
width: 1500px;
height:1000px;
border:1px solid red;
display: table-cell;
vertical-align: middle;
text-align: center;
}
img{
vertical-align: middle;
}
</style>
</head>
<body>
<div><img src="img/1.jpg"/></div>
<div><img src="img/5.jpg"/></div>
<div><img src="img/6.jpg"/></div>
</body>
不加text-align:center,是垂直居中
(2)自适应等高布局
<style type="text/css">
#box{
}
#pic{
display: table-cell;
vertical-align: middle;
text-align: center;
width: 1000px;
border: 1px solid red;
}
#text{
display: table-cell;
width: 1000px;
border: 1px solid red;
border-left: none;
padding: 10px;
}
</style>
</head>
<body>
<div id="box">
<div id="pic">
<img src="img/1.jpg"/>
</div>
<div id="text">
<span>
在这个例子中,左右两个盒子我们都没有设置宽度,而是由内容撑开,但是我们会发现两个盒子的高度相等,并且高度由两个盒子的最大值决定,这就是自适应的等高布局。
大家可能就会问了,这种等高布局有什么用,其实等高布局的用途非常广泛,比如,我们每天都看的QQ空间的评论区就是用的等高布局。
在这个例子中,左右两个盒子我们都没有设置宽度,而是由内容撑开,但是我们会发现两个盒子的高度相等,并且高度由两个盒子的最大值决定,这就是自适应的等高布局。
大家可能就会问了,这种等高布局有什么用,其实等高布局的用途非常广泛,比如,我们每天都看的QQ空间的评论区就是用的等高布局。 </span>
</div>
</div>
</body>
宽度由内容撑开,高度由两个盒子最大值决定,即自适应等高布局,适用于类似QQ空间的评论区
(3)自动平均划分元素
只要设置ul的宽度就会给li自动划分宽度
<style type="text/css">
ul{
display: table;
width: 300px;
}
li{
display: table-cell;
height: 50px;
color: azure;
line-height: 150px;
text-align: center;
}
ul li:nth-child(1){background-color: red}
ul li:nth-child(2){background-color: green}
ul li:nth-child(3){background-color: yellow}
ul li:nth-child(4){background-color: black}
ul li:nth-child(5){background-color: orange}
</style>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
外边距塌陷
原理:相邻的两个或多个盒子的外边距会组合成一个共同的外边距,称之为外边距塌陷,外边距的高度等于两个发生叠加的外边距中较大的一方,一个盒子如果没有上填充和上边框,那么它的上边距会和文档流的第一个子元素的上边距重叠
只有普通文档流中块元素的垂直外边距会发生外边框合并,行内框、浮动框或者绝对定位之间的外边距不会合并
出现情况
- 相邻兄弟姐妹元素
父元素和子元素
父元素的上外边距和第一个子元素的上外边距 父元素的下外边距和最后一个子元素的下外边距
空元素
自己的上边距会和自己的下边距合并
解决方法
- 父级元素加overfloat:hidden
- 父级元素加padding-top
- 父级元素加position:absolute
float引起的高度塌陷
原理:父元素的高度是由子元素内容撑开,但是当子元素浮动时,父元素的高度变为零,此时就出现了塌陷
<style type="text/css">
.content{
background-color: #ff5555;
}
h1,p{
float: left;
}
p{
margin-top: 1rem;
font-size: 1rem;
}
</style>
</head>
<body>
<div class="content">
<h1>
沉默的大多数
</h1>
<p>
我现在写的东西大体属于文学的范畴,所谓文学,在我看来就是:先把文章写好看了再说,别的就不用管他妈的。除了文学,
我想不到有什么地方可以接受我这些古怪想法。赖在文学上,可以给自己在圈子中找到一个立脚点。有这样一个立脚点,就可以攻击这个圈子,攻击整个阳的世界。
</p>
<p>
几年前,我在美国读书。有个洋鬼子这样问我们:你们中国那个阴阳学说,怎么一切好的东西都属阳,一点不给阴剩下?当然,她这样发问,是因为她正是一个五体不全之阴人。但是这话也有些道理。话语权属于阳的一方,它当然不会说阴的一方任何好话。就是夫子也未能免俗,他把妇女和小人攻击了一通。这句话几千年来总被人引用,但我就没听到受攻击一方有任何回应。人们只是小心提防着不要做小人,
至于怎样不做妇人,这问题一直没有解决。就是到了现代,女变男的变性手术也是一个难题,而且也不宜推广——这世界上假男人太多,真男人就会找不到老婆。
</p>
</div>
解决方法
- 在父元素底部加上clear:both
<div class="content">
<h1>
沉默的大多数
</h1>
<p>
我现在写的东西大体属于文学的范畴,所谓文学,在我看来就是:先把文章写好看了再说,别的就不用管他妈的。除了文学,
我想不到有什么地方可以接受我这些古怪想法。赖在文学上,可以给自己在圈子中找到一个立脚点。有这样一个立脚点,就可以攻击这个圈子,攻击整个阳的世界。
</p>
<p>
几年前,我在美国读书。有个洋鬼子这样问我们:你们中国那个阴阳学说,怎么一切好的东西都属阳,一点不给阴剩下?当然,她这样发问,是因为她正是一个五体不全之阴人。但是这话也有些道理。话语权属于阳的一方,它当然不会说阴的一方任何好话。就是夫子也未能免俗,他把妇女和小人攻击了一通。这句话几千年来总被人引用,但我就没听到受攻击一方有任何回应。人们只是小心提防着不要做小人,
至于怎样不做妇人,这问题一直没有解决。就是到了现代,女变男的变性手术也是一个难题,而且也不宜推广——这世界上假男人太多,真男人就会找不到老婆。
</p>
<div style="clear: both;"></div>
</div>
通俗易懂,但是增加无意义标签,不方便后期维护
- 给父元素增加一行css
.content{
background-color: #ff5555;
float: left;
}
*用BFC给父元素增加css
.content{
background-color: #ff5555;
overflow:hidden
}
或者加display:table-cell;或display:table-caption;或display:inline-block;或position:fixed;或position:absolute等,这些都是触发了BFC
- 用css的after伪类
给父元素div添加一个clearfix的class类,然后设置CSS
.clearfix:after{
content: ".";
display: block;
height: 0px;
clear: both;
visibility: hidden;
}
<div class="content clearfix">
......
</div>
- 推荐使用–尼古拉斯大师方法
.clearfix:after,
.clearfix:before{
content: " ";
display: table;
}
.clearfix:after{
clear: both;
}
上述代码把display设置为table,可以创建一个匿名的表格单元,这个匿名的表格单元可以直接触发BFC,然后再直接设置content: ” “;,把内容设置为一个空格,这样就节省了不必要的代码。加上before主要目的是防止浏览器顶部的空白崩溃,即是指此盒子的margin-top与上一个盒子的margin-bottom会发生折叠,(在同一个BFC中两个毗邻的块级盒子在垂直方向(和布局有关系)的margin会发生折叠)。