面试之 css 篇

185 阅读14分钟

早学面试卷别人,不学面试被人卷!

一、BFC

什么是BFC呢?

  • BFC(Block formatting context),直译为"块级格式化上下文"。
  • 它是网页中一个独立的渲染区域(也成为formatting context)。
  • 这个渲染区域只有块级(Block)元素才能参与
  • 它规定了内部的块级元素如何布局。
  • BFC渲染区域内部如何布局,与区域外部毫不相干
  • 外部元素也不会影响BFC渲染区域内的元素。

简而言之,言而总之:

  • BFC就是页面上的一个隔离的独立渲染区域
  • 区域里面的子元素不会影响外面的元素。
  • 外面的元素也不会影响到区域里面的子元素。

说到这里,这就牵扯出,其实css中有2种渲染区域:

  1. 块级元素渲染区域
  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渲染区域:

  1. float的值不是none。
  2. position的值不是static或者relative。
  3. display的值是inline-block、table-cell、flex、table-caption或者 inline-flex。
  4. 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,本质就是%
这里是视口指的是浏览器内部的可视区域大小

%

通常认为子元素的百分比完全相对于直接父元素,但是,不总是相对于父元素的对应属性值
子元素的 topbottom 如果设置百分比,则相对于直接非 static 定位(默认定位)的父元素的高度
子元素的 leftright 如果设置百分比,则相对于直接非 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)是响应式设计的核心。

它根据条件告诉浏览器如何为指定视图宽度渲染页面