CSS宝典④-CSS布局秘籍(1)任督二脉BFC/IFC
HTML系列:
CSS系列:
- CSS基础知识筑基
- 常用CSS样式属性
- CSS选择器大全48式
- CSS布局秘籍(1)-任督二脉BFC/IFC
- CSS布局秘籍(2)-6脉神剑
- CSS动画-transition/animation
- CSS处理器-Less/Scss
01、CSS布局
1.1、正常布局流(Normal flow)
正常布局流 就是不做任何布局控制,按照HTML的顺序(从左到右,从上而下)进行布局排列。网页基于盒子模型进行正常的布局,主要特点:
- 盒子布局:单个内容的布局,把内容放入盒子,加上盒子三件套(padding、boder、margin)。
- 块盒子纵向布局:块级元素单独一行,按照顺序垂直排列,并按其margin分离。
- 内联盒子水平布局:内联元素会在一行水平排列,高度、宽度都取决于内容,直到空间不足另起一行(换行)。高矮不齐,底部对齐。
- 边距折叠:垂直相邻元素的垂直
margin
会保留最大的那一个,就是盒子的外边距折叠。 - 空白折叠:无论多少个连续空格、换行、tab,都会折叠为一个空格。
块元素 | 行内元素 | |
---|---|---|
是否换行 | 独占一行,从新的一行开始,其后也另起一行 | 和其他行内元素在同一行 |
大小设置 | 元素的高、宽、行高、边距、对齐都可调整,宽度默认100% | 元素高、宽、外边距不可设置,根据内容自适应 |
包含元素 | 一般可包含其他行内元素和块元素 | 一般可包含其他行内元素,不可包含块元素 |
常见元素 | div,form、table,h1-h6,p,pre,ul/ol/li,dt/dl,hr,br | span,font,input,textarea,label,img,a,button,select |
盒子 | 块级盒子 (block box):应用完整的盒子模型 | 内联盒子 (inline box):部分盒子模型有效 |
- 还有一种混合型“行内块元素”属于行内元素的一种,和其他元素在一行,但元素的高、宽、外边距都可以设置,如
button
、img
、input
。- 通过CSS样式的
display
属性可以更改元素的布局类型,如可设置<a>
为一个块元素布局display: block;
标准布局总是这样从左到右、从上而下的顺序排列。但当我们要实现一些特殊的的布局效果时就没法了,这时的办法就是 —— 🚫脱离文档流。
🚫脱离文档流,就是从正常文档流中移除,文档流布局就不考虑他了,也就不会占用空间。基本上可以这样理解,当然也不是绝对就没人管了,他的父容器还是管的,至于怎么管看《格式化上下文》。
常用的脱离文档流的方式:float
、position
- float浮动,会使元素脱离文档流,移动到容器左/右边,后面元素会围绕浮动元素。
- position定位,绝对定位(absolute)、固定定位(fixed),会使元素脱离文档流,空出来的位置被后续元素代替,所以会出现和其他元素重叠的问题。
1.2、display布局属性
正常流中的所有元素都有一个display
的值,这个属性允许我们更改默认的显示方式。display
用来设置多种布局方式,可让不同元素类型(行、块元素)转换。
属性/值 | 描述 |
---|---|
display | 设置元素显示类型,包括下面这些枚举值 |
none | 元素隐藏不显示,不占据空间、无交互,常用于隐藏元素 |
block | 此元素将显示为块级元素 |
inline | 内联,此元素会被显示为内联元素 |
inline-block | 行内块元素(CSS2.1),介于内联和块之间,除了不换行,高宽、盒子三件套都有效。 常用 <ul> 的<li> +inline-block 来实现导航 |
flex IE11 | 弹性盒子布局(横向布局),inline-flex 内联的弹性盒子 |
grid | 非常灵活的网格布局,有些属性IE不支持。inline-grid 内联的网格布局 |
list-item | 此元素会作为列表,类似<ul> ,父元素显示为 block 盒,内部变为多个 list-item inline 盒 |
table | 表格布局,同家族还有个inline-table 内联表格布局、table-row、table-cell |
contents | 伪盒子,充当遮罩的元素,不会产生任何盒子(不会被渲染),但不影响其子元素的布局和渲染 |
flow-root IE🚫 | 建立一个无副作用的BFC |
<span style="display:block">span元素2</span> <!--转换为块元素,类似一个div-->
<div style="display:inline">div元素</div> <!--转换为行内元素,类似一个span-->
02、什么是响应式布局?
2.1、响应式设计
响应式网页设计(responsive /rɪˈspɒnsɪv/ web design,RWD)指的是允许 Web 页面适应不同屏幕宽度等因素,进行布局和外观的调整的一系列实践。它涵盖了很多 CSS 和 HTML 的功能和技术,现在也基本是我们默认建设网站的方式。
如上图,基于媒体查询和现代布局,响应式设计成为当下的主流。通过媒体查询测试,针对不同的尺寸适配不同的CSS样式、图片,如调整字体大小、段落填充、菜单按钮布局、以及增大触摸按钮的大小等,让网页能够自适应各种设备尺寸、设备类型。
- 响应式图形,创建多种尺寸版本文件,基于
srcset
、sizes
,适配合适尺寸的文件。或者改用新的<picture>
元素。
<img srcset="elva-fairy-320w.jpg 320w,
elva-fairy-480w.jpg 480w,
elva-fairy-800w.jpg 800w"
sizes="(max-width: 320px) 280px,
(max-width: 480px) 440px,
800px"
src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">
- 响应式排版,传统方式可以结合vw单位(视口的1%)、固定尺寸rem、px单位,现在可以基于媒体查询设置不同样式规则。
.p1 {
font-size: calc(1rem + 2vw);
}
@media screen and (min-width:1440px) {
.p1 {
font-size: 150%;
}
}
- 视口元标签,明确视口的宽度为设备的宽度,并初始化缩放比例为1,建议添加如下元素申明。
<meta name="viewport" content="width=device-width,initial-scale=1">
2.2、@媒体查询
媒体查询是指针对不同的设备、特定的设备特征或者参数进行定制化的修改网站的样式,媒体查询的标准语法:
@media media-type and (media-feature-rule) { /* CSS规则 CSS rules go here */ } /* 注意关键字
and
后面的空格 */
属性 | 描述 | 值/备注 |
---|---|---|
@media | 媒体查询申明 | |
media-type | 媒体类型 | - all:所有设备 - screen:屏幕,常用 - speech:语音合成器;print:打印,网页打印的时候 |
逻辑操作符(and) | 连接多个媒体查询语句 | - and:查询条件都满足的时候才生效 - not:查询条件取反 - only:整个查询匹配的时候才生效,常用语兼容旧浏览器,使用时候必须指定媒体类型 - 逗号或者 or:查询条件满足一项即可匹配; |
media-feature-rule | 媒体特征规则,一些条件表达式,常用尺寸判断 | - min-width:>=最小宽度;max-width:<=最大宽度 - 更多媒体查询特征,如 orientation (屏幕方向) |
@import | 导入外部css样式,支持媒体查询 | @import url(example.css) screen and (width:800px) ; |
/* 媒体查询:在大尺寸模式启用flex布局,横向排列 */
@media screen and (min-width: 40em) {
.nav ul {
display: flex;
}
.nav li {
flex: 1;
}
}
响应式布局-代码示例(Codepen)
03、CSS的格式化上下文
所有元素都是一个盒子Box,盒子Box是页面布局的基本单位,盒子的不同类型决定了他的布局方式。一个页面由各种盒子的组合、嵌套形成。这些盒子各不相同,有些是横排,有些竖排,有些是弹性,有些是网格,那他们是如何布局的呢?这就必须要了解的一个概念——格式化上下文。
格式化上下文(Formatting Contexts),就是把页面内容分为多个不同的格式化上下文(区域),每个格式化上下文都是一个独立的渲染(布局)区域,存放同类型的盒子。根据盒子的不同,格式化上下文分为多种(四种)类型,每种类型有自己的渲染规则,决定了其内部子元素的定位、排列方式。
格式化上下文 | 简述 |
---|---|
BFC:块级格式化上下文 | Block fomatting context ,由块级盒子组成的上下文区域,纵向排列。需要重点了解的,浮动float 布局的各种坑就靠他来填了。 |
IFC:内联级格式上下文 | Inline formatting context,内联格式上下文,就是横向布局的内联盒子,由内联盒子构成 |
FFC:弹性盒格式化上下文 | Flexible Formatting Contex,就是flex 布局的弹性盒子,申明flex (或inline-flex )布局就是创建了一个FFC弹性盒子格式上下文。 |
GFC:网格格式化上下文 | Grids Formatting Context,就是grid (或inline-grid )布局的盒子,二维网格布局,使用很方便。不过由于兼容性问题(很多属性不支持IE),使用还不广泛,不过现代浏览器基本都支持了。 |
实际上这些格式上下文也是相互嵌套的,各自负责各自区域进行渲染(布局)。
上图仅为个人理解。
04、BFC-块级格式化上下文
Block fomatting context (= block-level box + Formatting Context),块级格式化上下文,简称 BFC。是一个独立的渲染(布局)区域,用于给块级盒子布局,包含的都是块级盒子。
🔸基本规则:
- 块级元素:首先BFC本身也是“块级盒子”(当然实际DOM中并没有这个盒子元素),其内部也都是块级元素盒子。
- 独立主权:该区域的内部无论有什么东西、如何排列、在干什么,都不影响其外部,反之亦然。
- 垂直排列:BFC内部的Box垂直排列,从上往下依次排列。
- 垂直 margin 重叠:垂直方向间距由
margin
决定,同一BFC内相邻的Box的margin
重叠,看谁的大就谁的。so,不是在同一个BFC则不会发生边距重叠。 - 左边距,BFC中每个盒子,都是从其父容器Box的左边界开始,包括浮动元素也是这样。
- 不会重叠:BFC区域不会与浮动盒子(float box)重叠,会向后找新的区域排列。注意❗,这是解决浮动盒子重叠的关键。
- BFC高度:计算BFC高度时,会包含浮动元素(float box)。注意❗,这是解决高度坍塌、清除浮动的关键。
🔸如何触发BFC?
html
根元素,最大的BFC。float
浮动:left、right,脱离了文档流,自成一派。自成一个独立BFC,它的内部是正常流布局。position
定位:absolute、fixed,脱离了文档流,自成一派,同float
浮动一样。overflow
溢出,属性值不为 visible,常用overflow: hidden
触发容器为BFC。display
值:一个块级盒子,为独立BFC区域:- 行内块级盒子:inline-block
- 表格类盒子:table、table-cell、table-caption、inline-table
- 弹性盒子:flex 、inline-flex
- 网格盒子:grid 、inline-grid
📢注意:上面这些场景会触发创建块格式化上下文,而不是这些盒子本身。
🔸使用场景
BFC主要还是浏览器用来渲染布局用的,在实际开发中可以利用他的这些规则做哪些事情呢?—— 处理浮动float
布局的烂摊子!
① float导致的高度塌陷
❓ 问题:如果一个块级盒子如<div>
中的元素都是float
,他们都脱离了文档流,会导致盒子高度塌陷,就是高度没了。这时就会影响后面元素的布局了,造成不想看到的情景,float
这个渣...
✅ 解决方法:触发这个容器的BFC
,因为BFC
在计算高度的时候会考虑内部的浮动元素,浮动元素本身也是一个独立BFC。
<div class="height-lose">
<div>div1</div>
<div>div2</div>
<i>艰难的撑起了一点高度</i>
</div>
<style>
.height-lose{
border:2px solid;
/* 建立BFC,防止高度塌陷 */
overflow: hidden;
/* display: table; */ /* 我也可以 */
}
.height-lose>div{
float: left;
height: 50px; width: 50px; margin: 5px;
background-color: antiquewhite;
}
</style>
» 父容器div
的高度坍塌,因为没有计算浮动元素。触发父容器BFC即可解决
② float导致的盒子重叠/环绕
❓ 问题:如下示例,父容器<div>
中,左侧子元素是浮动float
布局,导致后面正常元素与他重叠了,区域重叠,内容会绕开,看上去就是环绕效果。
✅ 解决方法:触发后面的的盒子为BFC
,防止重叠,因BFC不会和其他浮动元素重叠。这种方法还可以用来实现左右两栏布局。
<div class="left-right">
<div>left:左浮动box左浮动box</div>
<div>right:我是右边,你挡着我了!我是右边,不是左边,不要挡到我。</div>
</div>
<style>
.left-right div:first-of-type {
float: left;
width: 100px;
background-color: #7F7;
}
.left-right div:last-of-type {
width: 160px;
background-color: #77FA;
/* 右侧盒子触发BFC,防止被遮挡 */
overflow: hidden;
/* display: table; */ /* 我也可以 */
}
</style>
» 盒子重叠,内容环绕,触发BFC解决
③ 清除float浮动
由于浮动float
会导致后续正常布局的元素布局“不正常”,主要原因就是浮动float
盒子的父容器高度塌陷、元素重叠。因此解决方法也就是恢复其高度,触发其父元素的BFC即可,方法同上。
④ 边距重叠
❓ 问题:如下示例中,父容器<div>
,两个子元素<p>
的上下边距重叠了,有的时候这并不是希望看到的。
✅ 解决方法:原本这两个元素是在同一个BFC里,解决方式就是把一个<p>
元素放到另一个BFC
里,拆散他们!
<div class="margin-overlap">
<p>p1:margin:30px 0</p>
<div class="bfc">
<p>p2:margin:30px 0</p>
</div>
</div>
<style>
.margin-overlap p {
margin: 30px 0;
padding: 0 10px;
border: 2px solid skyblue;
line-height: 30px;
height: 30px;
}
.bfc {
/* 建立BFC,就是要打破你们的水乳交融 */
overflow: hidden;
/* display: table; */ /* 我也可以 */
}
</style>
05、IFC:内联级格式上下文
Inline formatting context ,内联级格式上下文,简称 IFC。包含行内元素盒子,从左到右横向排列成一行。形成条件比较简单,当块级元素中仅包含行内元素盒子时,就形成了一个IFC。很多时候都是浏览器自动用匿名块进行包装形成IFC
,如当IFC
中有块级元素插入时,会拆分产生两个IFC
。
基本规则:
- 水平排列:IFC内都是行内元素盒子,水平方向排列。
- 垂直对齐
vertical-align
:底部、顶部对齐,或者文本基线,不同元素默认对齐方式不同。 - 行框(line box):包含了一整行的行内盒子的矩形区域,被称为该行的行框(line box),宽度由内容决定,高度由CSS计算(最高的元素)。
- 多行-多行框:当一个IFC的内容比较多,会自动换行,会切分为多个行框(line box)。
- 水平间距:盒子之间水平margin、border、padding都有效,会推开其他盒子。
- 水平对齐
text-align
:当内容宽度小于行框时,水平渲染规则由text-align
来决定。所以一般可以用text-align:center;
来设置水平居中。 - 垂直间距:会有用,但不会计算垂直的空间,不影响行高、不影响其他元素布局。
- 默认有间隙:行内元素盒子之间有一个默认间隙。
<p>我只是路过而已!</p>
<div class="inline-box">
<span>span:padding:100px</span>
<img src="../res/qq.png" alt="图片" height="100px">
<p>p标签,inline-block</p>
</div>
<p>我是新的一个p盒子内容,我只是路过而已,别当到我了!</p>
<style>
.inline-box {
text-align: center; /*水平居中*/
background-color: aliceblue;
height: 130px;
/*line-height: 130px;*/ /* 基于line-height 垂直居中,子元素会继承*/
/* overflow: hidden; */ /* 隐藏溢出部分内容 */
}
.inline-box * {
background-color: #F666;
vertical-align: middle; /* 基于行框高度 垂直居中*/
}
.inline-box p {
display: inline-block;
margin: 0;
}
.inline-box span{
margin: 300px 0; /*margin没有卵用,如果为inline-block有用*/
padding: 100px 0; /*padding 会溢出,不影响其他元素布局,会重叠*/
border: 2px solid blue;
}
</style>
» 垂直的padding有效,超出了父容器边界
» 启用注释代码:
⁉️上面的示例中可得出如下结论:
- 行框的高度由长得最高的元素撑起来的。
- 垂直
margin
好像没什么用,padding
、border
部分有效,不会计算垂直空间,不影响其他元素布局,但会影响渲染,有重叠。 text-align: center;
,让行内元素水平居中布局显示。vertical-align: middle;
,可以让行内元素垂直居中显示(基于行框的高度,而不是父容器高度)。line-height: 130px;
,让行内元素基于line-height
垂直居中。
©️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀