一、布局方式介绍
布局模型是基于盒模型基础上进行的拓展,关于布局有流式布局(标准的布局),浮动布局、定位布局、flex布局等。
1.1 标准流(流动模型)
描述:元素按照自己默认的元素类型在页面中进行排列的方式叫做标准流布局。
1.2 按照元素的框类型分类
-
块块元素block
前后具有换行符,默认独占一行。
可以设置宽高,设置宽高后容器范围为设置的宽高的范围,但换行符一直存在。
设置上下外边距存在合并问题。
非块状元素设置为块状元素 display:block;
目前学过的块状元素 h1-h6 p div 等
-
行内元素inline
在同一行内与其它行内级元素从左到右依次排列。默认包裹内容。
行内元素不能设置宽高。
设置左右外边距生效,上下外边距不生效;
设置左右内填充生效,上下内填充不生效(不占位,不会撑大盒子,但是背景色又呈现);
非行内元素设置为行内元素 display:inline;
目前学过的行内元素 span a strong em ins del 等
-
行内块元素 inline-block
在同一行内与其它行内级元素从左到右依次排列。默认包裹内容。
可以设置宽高,设置宽高后容器范围为设置的宽高的范围。
所有的外边距和内填充都是生效的。
非行内块元素设置为行内块元素 display:inline-block;
常见的行内块元素 input textarea select img等
总结:标准流中,块级元素block在页面中从上往下依次排列,行内级元素(inline、inline-block)在同一行内从左到右依次排列,超出父容器后自动换行。如果文本内容没有使用元素进行包裹,那么被识别为匿名行内元素。
二、浮动布局
2.1 浮动的概念
-
浮动模型:用来改变块元素(block element)对象的默认显示方式。block对象设置了float属性之后,它将本来占据一行的元素,可以并列排在一行里。
-
设置浮动属性, 可以向左侧或右侧,浮动的框就因此向左或向右移动,直到它的外边缘碰到包含框(浮动元素的包含块是其最近的块级祖先元素)或另一个浮动框的边框为止。
-
通过属性 float 设置元素的浮动,对应的属性值
- left (左浮动 )
- right ( 右浮动 )
- none ( 默认,不浮动 )
-
浮动设计的初衷,仅仅是为了在排版中,实现文字环绕图片效果
<div style="background-color: #f5f5f5;"> <img src="img/3.jpg"> <p> ....</p> </div>
以上代码使用样式对img设置左浮动,p不设置浮动,适量增加p中的内容,缩放视口查看效果; 脱离了文档流(是相对于普通文档流来说的),该元素就不在占空间,因此在计算高度时这个元素就不考虑,上面本身div没有设置高度,它的高度由元素里的内容 与元素里的内容高度共同决定(把父元素撑开),当元素设置浮动后,它就脱离文档流,在标准流中,就只有元素一个,元素就自然排在上面去了,此时 父元素div的高度就是由元素里的内容的高度决定。(也就是经常说的,父元素会塌陷问题,道理就在这)脱离文档流只是在视觉上这个元素还是占据空间的,图片元素 不会覆盖其他元素内容(这里内容俩字很重要,也充分说明了在使用float脱离文档流时,其他盒子会无视这个元素,但其他盒子内的文本内容依然会为这个元素让出位置, 环绕在周围),或不被其他元素内容覆盖,如以下操作:在以上代码基础上,div外新增一个p元素,添加文本内容,然后将div内部img和p元素设置左浮动,查看效果
2.2 浮动的特性
- 浮动模型改变了元素的默认排列方式,可以使元素紧密排列(按照设置浮动的方向依次贴边显示)
- 浮动后的元素都具有了块级元素的特点
- 设置浮动后的元素,不存在上下外边距合并的问题
- 浮动的元素脱离了标准的文档流,不在文档流中占位置,且会形成压盖效果,前面设置浮动的元素压盖后面标准流中的元素
- 子元素设置浮动,父元素在没有设置高度的情况下,会呈现塌陷的效果
2.3 清除浮动
-
为什么要清除浮动
当父元素不设置高度或者设置的高度小于子元素;而子元素又设置了浮动,那么会造成父元素塌陷。如下,子元素全部设置浮动后,父元素塌陷效果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SYUc4rBu-1687136272709)(浮动与定位.assets/clip_image002.jpg)]
-
清除浮动的属性 clear,属性值
- left 清除左浮动
- right 清除右浮动
- both 清除左右浮动,常用
-
清除浮动的方式(至少需要讲以下四种)
-
父元素设置合理的高度
这种方式可以解决视觉上父元素塌陷问题,但元素还是浮动的效果;
且在页面布局中,更多的容器其实是被内容撑起来的,在一开始布局的时候,父元素的高度其实是不太好确定的,所以除非是明确尺寸的布局,否则不建议使用这种方式
-
父元素设置
overflow:hidden|scroll |auto
属性描述:通过给父元素设置overflow:hidden | scroll | auto
问题:如果子元素及内容不超出父元素,用起来很方便。但是如果有定位存在需要将子元素定位到父元素外的某个位置,那么溢出的部分就看不到了。根据实际情况使用。
-
利用空元素(内墙或外墙)
描述:这种方式是在父元素内部的最后,添加一对空标签,然后给这个空标签设置清除浮动clear:both
问题:当页面应用浮动过多的时候,会增加html空标签的数量,一方面影响加载速度,另一方面也不美观
-
after 伪类清浮动(推荐)
这种方法是推荐使用的,bootsrtap也在使用,应该掌握,不然太low了,他的原理就是通过伪元素选择器,在div后面添加了一个clear:both的属性,跟第三种方法是一样的道理。
如下:给父元素添加一个伪元素
.clearfix::after{ display: block; height: 0; content: ''; clear: both; visibility: hidden; } .clearfix{ //兼容低版本IE zoom:1; }
-
了解其它清除浮动的方式
-
给父元素设置浮动,会造成新的问题
-
给父元素设置
display:table;
将div属性变成表格,会产生新的未知问题
-
使用双伪元素清除浮动
.clearfix:after,.clearfix:before{ content:''; display:block; clear:both; } .clearfix{ //兼容低版本IE zoom:1; }
-
-
三、定位
3.1 定位的概念
日常生活中,去到某个陌生的城市,我们通常打开手机地图,定位自己当前位置和要去的位置,查找所对应的路线。
在CSS中的定位,道理其实差不多。就是给当前元素进行位置的处理。
W3CSchool规定定位的基本思想:它允许你定义元素框相对于其正常位置应该出现的位置,或者相对于父元素、另一个元素甚至浏览器窗口本身的位置。
参考文档:https://www.w3school.com.cn/css/css_positioning.asp
3.2 定位的种类
- 静态定位static
- HTML 元素的默认值,即没有定位,遵循正常的文档流对象。
- 静态定位的元素不会受到 top, bottom, left, right影响。
- 相对定位relative
- 元素框偏移某个距离。元素仍保持其未定位前的形状,它原本所占的空间仍保留。
- 相对定位元素经常被用来作为绝对定位元素的容器块。
- 绝对定位absolute
- 绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那么它的位置相对于 html
- absolute 定位使元素的位置与文档流无关,因此不占据空间。
- absolute 定位的元素和其他元素重叠。
- 固定定位fixed
- 元素的位置相对于浏览器窗口是固定位置。即使窗口是滚动的它也不会移动:
- 粘性定位
- sticky 英文字面意思是粘,粘贴,所以可以把它称之为粘性定位。
- position: sticky; 基于用户的滚动位置来定位。
- 粘性定位的元素是依赖于用户的滚动,在 position:relative 与 position:fixed 定位之间切换。它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 **position:fixed;**它会固定在目标位置。
- 元素定位表现为在跨越特定阈值前为相对定位,之后为固定定位。
- 这个特定阈值指的是 top, right, bottom 或 left 之一,换言之,指定 top, right, bottom 或 left 四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同。
3.3 位置相关属性
top | right | bottom | left
3.4 z-index 属性
元素的定位与文档流无关,所以它们可以覆盖页面上的其它元素
z-index属性指定了一个元素的堆叠顺序(哪个元素应该放在前面,或后面),属性值为 number 数字
一个元素可以有正数或负数的堆叠顺序,一般设置大于0的数字
具有更高堆叠顺序的元素总是在较低的堆叠顺序元素的前面。
如果两个定位元素重叠,没有指定z - index,最后定位在HTML代码中的元素将被显示在最前面。
3.5 压盖顺序:
通过z-index设置,属性值大于0的数字
1)第一种情况:设置了定位压盖没有设置定位的元素
2)第二种情况:设置了非静态定位的同级元素之间默认后面压盖前面;如果设置z-index,值越大,越靠上
3)第三种情况,嵌套的元素,父元素的z-index决定压盖的顺序
四、弹性盒子
4.1 概述
- 弹性盒子是 CSS3 的一种新的布局模式。
- CSS3 弹性盒( Flexible Box 或flexbox),是一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式。
- 引入弹性盒布局模型的目的是提供一种更加有效的方式来对一个容器中的子元素进行排列、对齐和分配空白空间。
- 弹性盒子由弹性容器(Flex container)和弹性子元素(Flex item)组成。
4.2 弹性盒组成
-
弹性盒容器:通过设置 display 属性的值为 flex 或 inline-flex 将其定义为弹性容器。
- 弹性容器内包含了一个或多个弹性子元素。
- 弹性容器外及弹性子元素内是正常渲染的(即盒子内外其它元素属性效果)。弹性盒子只定义了弹性子元素如何在弹性容器内布局。
- 弹性子元素通常在弹性盒子内一行显示。默认情况每个容器只有一行。但是可以通过设置
direction
属性值为rtl
, 使弹性子元素的排列方式发生改变,页面布局也跟着改变(改变子元素的排列方式);
-
弹性子元素:盒子里面的元素
4.3 弹性盒容器六大属性介绍
-
flex-direction
指定了弹性子元素在父容器中的位置,属性值如下- row:横向从左到右排列(左对齐),默认的排列方式。
- row-reverse:反转横向排列(右对齐,从后往前排,最后一项排在最前面。
- column:纵向排列。
- column-reverse:反转纵向排列,从后往前排,最后一项排在最上面。
-
flex-wrap:wrap
设置盒子内部元素的换行方式,在页面缩放时,水平方向溢出部分可以进行换行 -
flex-flow
复合属性,用于同时设置子元素的位置和换行方式注意:如果元素不是弹性盒对象的元素,则 flex-flow 属性不起作用。
-
justify-content
应用在弹性容器上,把弹性项沿着弹性容器的主轴线(main axis)对齐,属性值如下- flex-start:弹性项目向行头紧挨着填充。这个是默认值。
- flex-end:弹性项目向行尾紧挨着填充。
- center:弹性项目居中紧挨着填充。
- space-between:弹性项目平均分布在该行上。
- space-around:弹性项目平均分布在该行上,两边留有一半的间隔空间。
-
align-items
设置或检索弹性盒子元素在侧轴(纵轴)方向上的对齐方式,属性值如下- flex-start:弹性盒子元素的侧轴(纵轴)起始位置的边界紧靠住该行的侧轴起始边界。
- flex-end:弹性盒子元素的侧轴(纵轴)起始位置的边界紧靠住该行的侧轴结束边界。
- center:弹性盒子元素在该行的侧轴(纵轴)上居中放置。(如果该行的尺寸小于弹性盒子元素的尺寸,则会向两个方向溢出相同的长度)。
-
align-content:类似于justify-content,子元素根据设置的属性值在Y方向进行不同的排列方式,属性值如下
- stretch - 默认。各行将会伸展以占用剩余的空间。
- flex-start - 各行向弹性盒容器的起始位置堆叠。
- flex-end - 各行向弹性盒容器的结束位置堆叠。
- center -各行向弹性盒容器的中间位置堆叠。
- space-between -各行在弹性盒容器中平均分布。
- space-around - 各行在弹性盒容器中平均分布,两端保留子元素与子元素之间间距大小的一半
4.4 弹性项六大属性介绍
- order 排序。属性值为整数,用整数值来定义排列顺序,数值小的排在前面。可以为负值
- align-self:用于设置弹性元素自身在侧轴(纵轴)方向上的对齐方式
- auto:如果’align-self’的值为 auto,则其计算值为元素的父元素的 align-items 值,如果其没有父元素,则计算值为 stretch。
- flex-start:弹性盒子元素的侧轴(纵轴)起始位置的边界紧靠住该行的侧轴起始边界。
- flex-end:弹性盒子元素的侧轴(纵轴)起始位置的边界紧靠住该行的侧轴结束边界。
- center:弹性盒子元素在该行的侧轴(纵轴)上居中放置。(如果该行的尺寸小于弹性盒子元素的尺寸,则会向两个方向溢出相同的长度)。
- baseline:如弹性盒子元素的行内轴与侧轴为同一条,则该值与’flex-start’等效。其它情况下,该值将参与基线对齐。
- stretch:如果指定侧轴大小的属性值为’auto’,则其值会使项目的边距盒的尺寸尽可能接近所在行的尺寸,但同时会遵照’min/max-width/height’属性的限制。
- flex-grow 属性用于设置或检索弹性盒的扩展比率,属性值为数字即可,默认值是 0
- flex-shrink 属性指定了 flex 元素的收缩规则。flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值。
- flex-basis 属性用于设置或检索弹性盒伸缩基准值 属性值一个长度单位或者一个百分比,规定灵活项目的初始长度
- flex:指定弹性子元素如何分配空间,即所占比重,一般设置为数值即可;可以作为flex-grow、flex-shrink、flex-basis元素的简写方式:
设置元素垂直居中:
- 块元素垂直居中问题采用 flex 解决
- 行内元素垂直居中问题解决如下
- 单行 该元素
css
属性 line-height 的值与该元素的父级元素css
属性 height 一致即可 - 多行 设置该元素
css
属性:display: table-cell; vertical-align: middle;,还需设置该元素的父级元素css
属性:display: table;
- 单行 该元素
五、固比固布局
三栏布局 左右固定 中间自适应
-
使用浮动实现:左 float + 右 float + 中 设为 BFC(
overflow:hidden
)HTML结构:
<div class="left">左</div> <div class="right">右</div> <div class="main">content area</div>
CSS样式:
.container { height:100%; .left { float: left; height: 100%; width:100px; background-color:lightblue; } .right { float: right; height: 100%; width:100px; background-color:lightgreen; } .main { height:100%; overflow:hidden; background-color:lightpink; } }
-
使用定位实现 左
absolute
+ 右absolut
+ 中margin
上面 HTML 结构 left right 和 main,顺序可以随意调换
CSS代码:
.container { height:100%; position:relative; .left { position:absolute; left:0; top:0; height: 100%; width:100px; background-color:lightblue; } .right { position:absolute; right:0; top:0; height: 100%; width:100px; background-color:lightgreen; } .main { height:100%; margin:0 100px; background-color:lightpink; } }
-
使用弹性盒子实现
HTML代码:
<div class="wrap"> <aside class="left">左边栏</aside> <div class="center">中间栏</div> <aside class="right">右边栏</aside> </div>
CSS代码:
.wrap{ /*设置父元素为弹性盒*/ display: flex; height: 400px; background-color: lightgray; } .left{ width: 260px; height: 100%; background-color: red; } .center{ width: 320px; height: 120%; /*设置弹性子元素的属性,对剩余空白空间的分配比重*/ flex: 1; background-color: #00b1e8; } .right{ width: 320px; height: 100%; background-color: yellow; }
六、双飞翼 和 圣杯布局
在面试时,你会经常遇到那么一个考题?有left、right、container三个盒子,要求left与right盒子宽度固定,分别固定于浏览器两侧,container位于中间,
宽度随浏览器窗口自适应;说白了,就是要你进行两边定宽,中间自适应的三栏布局,并且中间栏要放在文档流前面以优先渲染。而圣杯布局与双飞翼布局就是用
来解决这个问题最常见的布局方法。
圣杯布局的出现是来自于a list part上的一篇文章In Search of the Holy Grail。比起双飞翼布局,它的起源不是源于对页面的形象表达。在西方,圣杯是
表达“渴求之物”的意思。而双飞翼布局则是源于淘宝的UED,可以说是灵感来自于页面渲染
圣杯布局和双飞翼布局基本上是一致的,都是两边固定宽度,中间自适应的三栏布局,其中,中间栏放到文档流前面,保证先行渲染。解决方案大体相同,都是三
栏全部float:left浮动,区别在于解决中间栏div的内容不被遮挡上,圣杯布局是中间栏在添加相对定位,并配合left和right属性,效果上表现为三栏是单独分
开的(如果可以看到空隙的话),而双飞翼布局是在中间栏的div中嵌套一个div,内容写在嵌套的div里,然后对嵌套的div设置margin-left和margin-right,
效果上表现为左右两栏在中间栏的上面,中间栏还是100%宽度,只不过中间栏的内容通过margin的值显示在中间。
简单说起来就是:双飞翼布局比圣杯布局多创建了一个div,但不用相对布局了。
双飞翼布局的好处:
- 主要的内容先加载的优化
- 兼容目前所有的主流浏览器,包括IE6在内
- 实现不同的布局方式,可以通过调整相关CSS属性即可实现
拓展:BFC概念
官方文档:https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context
1. Box、Formatting Context的概念
-
Box
Box 是 CSS 布局的对象和基本单位, 直观点来说,就是一个页面是由很多个 Box 组成的。元素的类型和 display 属性,决定了这个 Box 的类型。 不同类型的 Box, 会参与不同的 Formatting Context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。让我们看看有哪些盒子:
- block-level box:display 属性为 block, list-item, table 的元素,会生成 block-level box。并且参与 block fomatting context;
- inline-level box:display 属性为 inline, inline-block, inline-table 的元素,会生成 inline-level box。并且参与 inline formatting context;
- run-in box: css3 中才有, 这儿先不讲了。
-
Formatting context
Formatting context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。
CSS2.1 中只有
BFC
和IFC
, CSS3 中还增加了GFC
和FFC。
2. 什么是 BFC ?
BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
3. BFC布局规则
- 内部的Box会在垂直方向,一个接一个地放置。
- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
- 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算
4. 哪些元素会生成BFC ?
-
根元素html
-
float属性不为none
-
position为absolute或fixed
-
display为inline-block, table-cell, table-caption, flex, inline-flex
-
overflow不为visible
参考文档:https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context
5. BFC作用及原理
-
自适应两栏布局
<style> body { width: 300px; position: relative; } .aside { width: 100px; height: 150px; float: left; background: #f66; } .main { height: 200px; background: #fcc; } </style> <body> <div class="aside"></div> <div class="main"></div> </body>
效果
根据BFC
布局规则第3条:
每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
因此,虽然存在浮动的元素aslide,但main的左边依然会与包含块的左边相接触。
根据BFC
布局规则第四条:
BFC
的区域不会与float box
重叠。
我们可以通过通过触发main生成BFC
, 来实现自适应两栏布局。
.main {
overflow: hidden;
}
当触发main生成BFC
后,这个新的BFC
不会与浮动的aside重叠。因此会根据包含块的宽度,和aside的宽度,自动变窄。效果如下:
-
清除内部浮动
<style> .par { border: 5px solid #fcc; width: 300px; } .child { border: 5px solid #f66; width:100px; height: 100px; float: left; } </style> <body> <div class="par"> <div class="child"></div> <div class="child"></div> </div> </body>
页面效果:
根据BFC
布局规则第六条:
计算
BFC
的高度时,浮动元素也参与计算
为达到清除内部浮动,我们可以触发par生成BFC
,那么par在计算高度时,par内部的浮动元素child也会参与计算。
代码:
.par {
overflow: hidden;
}
页面效果:
-
防止垂直 margin 重叠
<style> p { color: #f55; background: #fcc; width: 200px; line-height: 100px; text-align:center; margin: 100px; } </style> <body> <p>Haha</p> <p>Hehe</p> </body>
页面效果:
两个p之间的距离为100px,发送了margin重叠。
根据BFC布局规则第二条:Box
垂直方向的距离由margin决定。属于同一个BFC
的两个相邻Box
的margin会发生重叠我们可以在p外面包裹一层容器,并触发该容器生成一个
BFC
。那么两个P便不属于同一个BFC
,就不会发生margin重叠了。
代码:<style> .wrap { overflow: hidden; } p { color: #f55; background: #fcc; width: 200px; line-height: 100px; text-align:center; margin: 100px; } </style> <body> <p>Haha</p> <div class="wrap"> <p>Hehe</p> </div> </body>
页面效果:
6. 总结
其实以上的几个例子都体现了BFC
布局规则第五条:
BFC
就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
因为BFC
内部的元素和外部的元素绝对不会互相影响,因此, 当BFC
外部存在浮动时,它不应该影响BFC
内部Box的布局,BFC
会通过变窄,而不与浮动有重叠。同样的,当BFC
内部有浮动时,为了不影响外部元素的布局,BFC
计算高度时会包括浮动的高度。避免margin重叠也是这样的一个道理。