早学面试卷别人,不学面试被人卷!
一、BFC
什么是BFC呢?
- BFC(Block formatting context),直译为"块级格式化上下文"。
- 它是网页中一个
独立的渲染区域
(也成为formatting context)。 - 这个渲染区域
只有块级(Block)元素才能参与
。 - 它规定了内部的块级元素如何布局。
- BFC渲染区域内部如何布局,
与区域外部毫不相干
。 - 外部元素也不会影响BFC渲染区域内的元素。
简而言之,言而总之:
- BFC就是页面上的一个隔离的
独立渲染区域
。 - 区域
里面
的子元素不会影响
到外面
的元素。 外面
的元素也不会影响
到区域里面
的子元素。
说到这里,这就牵扯出,其实css中有2种渲染区域:
- 块级元素渲染区域
- 行级元素渲染区域
块级元素渲染区域:
所有 display 属性为 block, list-item, table 的元素,会生成块级元素渲染区域。块级元素渲染区域内以BFC(block fomatting context)方式渲染,同级别的块级元素会垂直排列,每个块元素独占一行。
行级元素渲染区域:
display 属性为 inline, inline-block, inline-table 的元素,会生成行级元素渲染区域。行级元素渲染区域内以IFC(inline formatting context)方式渲染,同级别的行级元素会水平排列。
哎,说到这里,又要牵扯出,BFC的布局规则:
- 属于同一个BFC的块级元素会
垂直排列
,每个块元素独占一行。 - 块元素垂直方向的总距离由
边框内大小+margin
共同决定。 - 属于同一个BFC的两个相邻块元素在
垂直方向上的margin会发生重叠/合并
。但水平方向的margin不会。 - 计算父元素BFC渲染区域的高度时,内部浮动元素的高度,都必须算在内。
哈哈,说了这么多,那什么情况会形成BFC渲染区域:
- float的值不是none。
- position的值不是static或者relative。
- display的值是inline-block、table-cell、flex、table-caption或者 inline-flex。
- overflow的值不是visible。
哎,说了这么多,知道了这些,那有什么用呢?能解决什么问题呢?
对,就是可以解决一些实际问题,比如:形成BFC区域可以解决高度坍塌;形成BFC区域可以避免垂直方向margin合并;形成BFC区域可以避免垂直方向margin溢出;形成BFC区域可以实现左定宽,右自适应布局;
防止高度塌陷的几种方案
什么是高度塌陷?
当父元素的高度未设定时,那么父元素的高度都是由内部未浮动子元素的高度撑起的。如果子元素浮动起来,就不占用普通文档流的位置。父元素高度就会失去支撑,就称为高度坍塌
。
其实有人会说,那就给父元素设置高度呀!但是,这样有很大的缺点:多数情况下,父元素高度由内容撑起,很难提前固定父元素的高度。
1、为父元素设置overflow:hidden
属性。
原理:CSS中的overflow:hidden
属性会强制要求父元素必须包裹住所有内部浮动的元素,以及所有元素的margin范围。
缺点:如果刚好父元素有些超范围的子元素内容需要显示(比如:个别position定位的子菜单项),不想隐藏,就会发生冲突。
2、在父元素内的结尾追加一个空子元素(块级元素),并设置空子元素清除浮动影响(clear:both
) 。
原理: 利用clear:both
属性和父元素必须包含非浮动的元素两个原理。
缺点: 无端多出一个无意义的看不见的空元素,影响选择器和查找元素。
3、设置父元素也浮动。
原理: 浮动属性也会强制父元素扩大到包含所有浮动的内部元素。
缺点: 会产生新的浮动影响。比如,父元素浮动,导致父元素之后平级的元素上移,被父元素挡住了。
解决: 设置父元素之后的平级元素清除浮动(clear:both
)。
4、为父元素末尾伪元素设置clear:both
。
父元素::after{
content:"";
display:table;
clear:both;
height:0
}
优点: 既不会影响显示隐藏,又不会影响查找元素,又不会产生新的浮动问题。
避免垂直方向margin合并的几种方案
什么是垂直方向margin合并?
垂直方向上,两个元素上下margin相遇时,两元素的间的总间距并不等于两个margin的和。而是等于最大的margin。小的margin会被大的margin吞并。
1、用一个外围块元素包裹下方元素,设置新外层元素overflow:hidden
。
原理: 新外层元素,变成一个BFC方式的渲染区域,就必须包裹内部子元素及子元素的margin。而且,内部元素不能超出范围影响外部,外部元素也不能进入BFC范围内,影响内部。
缺点: 如果父元素中部分自由定位的子元素,希望即使超出父元素范围,也能显示时,就冲突了。
2、父元素下第一个子元素前添加空<table>
3、父元素padding代替子元素margin
4、父元素+透明上边框
5、父元素::before{content:""; display:table}
原理: display:table,在子元素之前形成平级的BFC渲染区域。不允许子元素的margin进入::before范围内。
优点: 既不隐藏内容,又不添加新元素,又不影响高度。
避免垂直方向margin溢出的几种方案
什么是垂直方向margin溢出?
子元素设置margin-top,会超出父元素上边的范围,变成父元素的margin-top。而实际上,子元素与父元素之间,依然是没有margin-top的,效果不是想要的。
1、设置父元素overflow:hidden
原理: 父元素变成BFC渲染区域,就必须包裹内层子元素的margin
缺点: 万一有的子元素,即使溢出父元素,也希望显示呢?就会发生冲突。
2、为父元素添加上边框,颜色设置为透明(transparent)
原理: 这里不是BFC。而是因为边框本身可以阻隔margin溢出。
缺点: 边框会增大父元素的实际大小,导致布局错乱。
3、用父元素的padding-top
代替第一个子元素的margin-top
原理: 这里也不是BFC。而是因为padding本身可以阻隔margin溢出。
缺点: 对父元素高度有影响。
解决: 可以设置父元素box-sizing:border-box
。
4、在父元素内第一个子元素之前添加一个空<table></table>
原理: table的display属性默认相当于table,所以形成小的BFC渲染区域。其他元素的margin不能进入table范围内。就阻隔了margin向上溢出。
优点: 空table元素没有大小,不占用父元素控件。
缺点: 增加一个看不见的空元素,干扰查找元素。
5、最好的解决: 父元素::before{content:""; display:table;}
优点:既不隐藏内容,又不添加新元素,又不影响高度。
可以实现左定宽,右自适应布局
左边定宽元素左浮动:.left{float:left; width:固定宽}
右边元素不用右浮动,而是 .right{overflow:hidden; ...}
原理: 右边元素overflow:hidden后,形成BFC渲染区域。左边的float元素就不能进入右边范围了。
二、弹性布局
什么是弹性布局呢?
-
弹性布局的
容器
,简称“容器”,是指要实现布局效果的父元素。 -
弹性布局的
项目
,简称“项目”,是指要实现布局效果的子元素,称为项目。 -
主轴
,是指弹性布局的多个项目排列方向上的一根轴。- 如果弹性布局的多个项目按x轴排列,那么x轴就是主轴。
- 如果弹性布局的多个项目按y轴排列,那么y轴就是主轴。
-
交叉轴
,是指与主轴交叉的一根轴称为交叉轴。- 如果主轴是x轴,那么y轴就是交叉轴。
- 如果主轴是y轴,那么x轴就是交叉轴。
弹性布局的优点:自动计算、自适应
1、容器——使用弹性布局,都要先使父元素变为弹性布局的容器。
如果希望弹性布局的父元素独占布局中的一行,就要设置父元素的display属性为flex。
如果希望弹性布局的父元素显示为行内元素特征,与其它元素同在一行内,可设置父元素的display属性为inline-flex。
设置父元素为flex容器后,下一步就可以设置flex容器父元素的属性。
flex-direction属性,可指定容器的主轴及其排列方向
row,默认值,即主轴是x轴,项目从最左端开始向右排列
row-reverse,表示项目从最右侧开始,从右向左排列
column,主轴是y轴,项目从顶端开始,从上向下排列
column-reverse, 主轴是y轴,项目从底部向上排列
flex-wrap属性,专门设置当一个主轴排列不下所有项目时,是否换行显示
nowrap,默认值,表示空间不够时,也不换行,项目自动缩小
wrap,表示当内容放不下时应该换行显示
flex-flow属性,flex-direction flex-wrap 的简写形式
justify-content属性,专门定义项目在主轴上的对齐方式
flex-start,表示以主轴的起点对齐
flex-end,表示以主轴的终点对齐
center,表示在主轴上居中对齐
space-between,表示两端对齐
space-around,表示每个项目两端间距相同
align-items属性,专门定义所有项目在交叉轴上的统一对齐方式
flex-start,表示让项目以交叉轴的起点方向对齐
flex-end,表示让项目以交叉轴的终点方向对齐
center,表示让项目以交叉轴的中线居中对齐
baseline,表示让项目以交叉轴的基线对齐
stretch,表示如果项目未设置尺寸,就让项目在交叉轴上占满所有空间
2、项目
order属性
flex-grow属性,专门定义项目的放大比例
flex-shrink属性,专门定义项目的缩小比例
align-self属性,专门单独定义某一个项目在交叉轴上的对齐方式
三、居中的方法
水平居中
1、内联元素
行内元素可设置:text-align: center;
flex布局设置父元素:display: flex; justify-content: center;
2、块级元素
定宽: margin: 0 auto;
不定宽:参考下边例子中不定宽高的例子。
垂直居中
1、内联元素
单行文本父元素确认高度:height === line-height
多行文本父元素确认高度:display: table-cell; vertical-align: middle;
2、块级元素
position: absolute设置left、top、margin-left、margin-top(定高);
position: fixed设置margin: auto(定高);
display: table-cell;
transform: translate(x, y);
flex(不定高,不定宽);
grid(不定高,不定宽),兼容性相对比较差;
垂直和水平同时居中
1、定宽高
一、绝对定位 + 负margin值
二、绝对定位 + transform
三、绝对定位 + left/right/bottom/top + margin
四、flex布局
五、grid布局 + margin: auto;
六、table-cell + vertical-align + inline-block/margin: auto
2、不定宽高
一、绝对定位 + transform
二、table-cell + vertical-align + inline-block
三、flex布局
四、flex变异布局 + margin: auto;
五、grid + flex布局(align-self: center;justify-self: center;)
六、gird + margin布局(margin: auto;)
七、writing-mode属性布局
四、简述 rpx、px、em、rem、%、vh、vw的区别
设备物理像素pt
屏幕宽/分辨率,其中每一小份就是1pt
css像素px
pc机大屏幕显示器,1px约等于0.76个物理像素
手机小屏幕,以iPhone6为标准,物理像素750,分辨率375。
1px=2pt,所以,px也是一个相对单位
px是为了平衡一个元素在PC上显示的大小与在手机上显示的大小尽量一致而制定的。
但是,因为手机屏幕大小不一,差异较大,所以,反而不希望一个元素在所有手机上显示一样大。而是希望能够自动等比缩放。所以,移动端不要用px
通常PC端大屏浏览器的网页,使用px单位较多
移动端少用,因为px的长度相对固定,无法根据大小不一的移动端设备自适应改变大小
rem
以网页根元素 <html> ;元素上设置的默认字体大小为1rem
默认1rem=16px,用的比较多
可以实现响应式布局了!
响应式布局指的是元素大小能根据屏幕大小随时变化。
因为 所有以rem为单位的位置、大小都跟着根元素字体大小而变化。
所以只要在屏幕大小变化的时候改变根元素font-size就行了。
em
父元素的字体大小为1em
用的不多
rpx
小程序专用
以iPhone6为标准,物理像素750,分辨率375
无论屏幕大小,都将屏幕分成750份,每份就是1rpx。
1rpx=0.5px=1pt
通过 rpx 设置元素和字体的大小,小程序在不同尺寸的屏幕下,可以实现自动适配
vm/vh
CSS3 特性 vh 和 vw
vh ,无论视口高度多少,都将视口高均分为100份,每1小份就是1vh,所以,也是相对单位,可随视口大小变化而自动变化。
vw ,无论视口宽度多少,都将视口宽均分为100份,每1小份就是1vw,所以,也是相对单位,可随视口大小变化而自动变化。
所以vw和vh,本质就是%
这里是视口指的是浏览器内部的可视区域大小
%
通常认为子元素的百分比完全相对于直接父元素,但是,不总是相对于父元素的对应属性值
子元素的 top 和 bottom 如果设置百分比,则相对于直接非 static 定位(默认定位)的父元素的高度
子元素的 left 和 right 如果设置百分比,则相对于直接非 static 定位(默认定位的)父元素的宽度
子元素的 padding/margin 如果设置百分比,不论是垂直方向或者是水平方向,都相对于直接父亲元素的 width ,而与父元素的 height 无关。
因为%不总是相对于父元素的宽高或屏幕大小,所以,有坑,开发少用。
五、响应式布局的几种方式,以及媒体查询原理
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0">
viewport
视口
显示设备内部,真正实际可用于显示网页的区域大小
width
视口宽
device-width 等于物理设备宽
user-scalable
是否允许用户手工缩放网页
initial-scale=1.0
加载页面时,页面的缩放比例是1,表示不缩放,原网页大小展示
maximum-scale=1.0,minimum-scale=1.0
允许用户缩放网页的最大缩放比例和最小缩放比例
都是1,表示不允许用户使用过程中,中途缩放网页
flex布局
优点: 代码简单,布局方便
缺点:如果中间有内容,缩到最小就不会在小了
缺点:且左右侧的宽度变小了
父相子绝
优点:结合使用media可以实现响应式布局
缺点:代码写法复杂,布局较繁琐
缺点:如果不使用media平分屏幕,宽度小于600的情况下,右侧会覆盖左侧
grid布局
float布局
容易被挤压换行
使用rem作单位,等比缩放
首先,给根元素html设置一个字体大小;然后,其他尺寸单位全部用 rem;然后,监听屏幕的大小;然后,根据屏幕的大小按比例改变根节点字体的大小
因为 rem 的特性,其他的尺寸都是根据根节点字体的大小设定的,所以,根节点字体大小一变,其他所有尺寸都会按比例变大、或小。
大部分浏览器的字体有个最小值:12px。也就是缩小到 12px 后,字体不会继续缩小。
媒体查询
通过媒体查询来设置样式(Media Queries)是响应式设计的核心。
它根据条件告诉浏览器如何为指定视图宽度渲染页面