CSS常见面试题

257 阅读5分钟

1. 描述css盒子模型

盒子模型包含content/padding/border/margin

盒子模型分为IE盒子模型(box-sizing: border-box;)和标准盒子模型(box-sizing: content-box;)

IE盒子模型中content的宽高包含了padding和border

标准盒子模型中content的宽高与padding和border是分开算的

2. 行内元素和块级元素的水平居中怎么实现

行内元素水平居中:父级元素使用text-align: center;

块级元素水平居中有以下几种方式:

  • 将margin-left和margin-right设置为auto
<style>
.parent{
  width: 100%;
  height: 100px;
  border: 1px solid #000;
}
.child{
  background: red;
  width: 20px;
  height: 20px;
  margin: 0 auto;
}
</style>

<div class="parent">
  <div class="child"></div>
</div>
  • 使用position + transform
<style>
.parent{
  width: 100%;
  height: 100px;
  position: relative;
  border: 1px solid #000;
}
.child{
  background: red;
  width: 20px;
  height: 20px;
  position: absolute;
  z-index: 1;
  top: 0;
  left: 50%;
  transform: translate(-50%, 0);
}
</style>

<div class="parent">
  <div class="child"></div>
</div>
  • transform兼容性不好,那么上面例子的child样式这样写也可以:
.child{
  width: 20px;
  height: 20px;
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  margin-top: -10px;
  margin-left: -10px;
}
  • 使用flex
<style>
.parent{
  width: 100%;
  height: 100px;
  display: flex;
  justify-content: center;
  border: 1px solid #000;
}
.child{
  background: red;
  width: 20px;
  height: 20px;
}
</style>
  • inline-block + text-align
<style>
.parent{
  width: 100%;
  height: 100px;
  text-align: center;
  border: 1px solid #000;
}
.child{
  background: red;
  width: 20px;
  height: 20px;
  display: inline-block;
}
</style>

3. 实现元素垂直居中

  • 使用position + transform
<style>
.parent{
  width: 100%;
  height: 100px;
  position: relative;
  border: 1px solid #000;
}
.child{
  background: red;
  width: 20px;
  height: 20px;
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 0;
  transform: translate(0, -50%);
}
</style>

<div class="parent">
  <div class="child"></div>
</div>
  • 使用flex
.parent{
  width: 100%;
  height: 100px;
  display: flex;
  align-items: center;
  border: 1px solid #000;
}
.child{
  width: 20px;
  height: 20px;
  background: red;
}
  • 使用table-cell + vertical-align
.parent{
  width: 100px;
  height: 100px;
  border: 1px solid #000;
  display: table-cell;
  vertival-align: middle;
}
.child{
  width: 20px;
  height: 20px;
  background: red;
}

4. 页面自适应方案

  • 使用媒体查询@media编写多套布局方案

  • 使用rem为单位,然后通过js计算给根元素一个font-size基数

//js部分
(function(doc, win){
  let maxWidth = 750;
  let docEle = doc.documentElement;
  let dpr = parseInt(window.devicePixelRatio || 1, 10);
  docEle.setAttribute('data-dpr', dpr);
  docEle.setAttribute('max-width', maxWidth);
  
  const recalc = function() {
    let clientWidth = docEle.getBoundingClientRect().width || docEle.clientWidth;
    if(clientWidth / dpr > maxWidth) {
      clientWidth = maxWidth * dpr;
    }
    docEle.style.fontSize = (clientWidth / maxWidth) + 'px';
  }
  
  recalc();
  
  if(!win.addEventListener) return;
  win.addEventListener('resize', recalc, false);
})(document, window)

//css部分
<style>
.banner{
  width: 100%;
  height: 400rem; /*相当于设计图中的400px*/
}
</style>

5. 解释一下CSS的BFC

BFC翻译成中文是块级格式化上下文,是一个独立的渲染区域或者说是一个隔离的独立容器。

形成BFC的条件:

  • 浮动元素,float除none以外的值
  • 定位元素,position(absolute/fixed)
  • display是inline-block/table-cell/table-caption
  • overflow除了visible以外的值

BFC能用来做的事情:

  • CSS的常规文档流中,两个兄弟元素之间的垂直margin由较大的一方决定,如果希望margin按照两个元素的margin之和来算,就可以使用overflow:hidden;把父级设置成BFC。
  • 比如要做一个两栏布局,左边的元素宽度固定,右边的元素宽度自适应,那么就可以给左边元素一个float: left;右边元素使用overflow: hidden;转换成一个BFC。
  • 一个加了float浮动的元素,会让一个旁边的正常元素形成环绕效果,想要取消环绕效果,可以使用overflow: hidden;将正常元素转换成一个BFC。
  • 想要解决父容器高度塌陷问题,可以使用overflow: hidden;将父容器转换成一个BFC。

6. 伪元素和伪类的区别

伪元素:dom树中创建的抽象元素,在html源码中是不可见的,比如::before,::after

伪类:获取不存在于dom树中的信息或不能被常规css选择器获取的信息,比如:link,:active,:visited,:focus,:hover,:first-child,:last-child,:nth-child(even)

7. 是否使用过样式预处理工具,比如sass或less,它们有什么用处

它们是基于css的功能强大的扩展语言,通过扩展出很多强大特性,让程序员可以更优雅方便的编写样式代码,这套扩展语言不能直接在浏览器中运行,需要通过构建工具将sass或less编译成css语言。

我常使用的样式预处理工具是scss,配合其扩展的特性,确实极大的方便了样式的编写,我常用的scss特性有:

  • 选择嵌套器
.list{
  .item{
    display: inline-block;
    width: 200px;
    height: 100px;
  }
  
  &::after{
    content: "";
    display: block;
    clear: both;
  }
}
  • 变量
$colorRed: #ff0000;

.text{
  color: $colorRed;
}
  • 混入
@mixin mxClearfix {
  display: block;
  content: "";
  clear: both;
}

.clearfix{
  @include mxClearfix;
}
  • 函数
@function fnGetHeight($val) {
  @return $val/2 + px;
}

.item{
  width: 100px;
  height: fnGetHeight(100);
}

8. transition和animation的区别

  • transition是过渡属性,往往需要一个动作来触发动画,比如鼠标滑过、焦点、点击等
div{
  width: 20px;
  height: 20px;
  background: red;
  transition: 1s 1s height linear;
}

div:hover{
  height: 60px;
}
  • animation是动画属性,不需要触发动作,自己就可以执行
.div{
  width: 20px;
  height: 20px;
  background: red;
  opacity: 1;
  animation: 3s changeOpacity linear infinite;
}

@keyframes changeOpacity{
  from{
    opacity: 1;
  }
  to{
    opacity: 0;
  }
}

9. 对position: sticky有了解吗?

position: sticky是粘性定位,页面不滑动的时候,position: sticky表现的与position: relative一样,当页面元素滚动并达到粘性定位的位置要求时(比如top: 100px),则会表现得与position: fixed一样。

使用条件:

  • 父元素不能是overflow: auto;或overflow: hidden;
  • 必须指定top/left/right/bottom其中的一个值,不然效果始终相当于position: relative;
  • 父元素的高度不能低于sticky元素的高度
  • sticky元素只在其父元素内生效

使用中的问题:

  • sticky元素不会触发BFC
  • z-index无效
  • 兼容性不好

10. 请实现一个垂直方向的三行布局,第一行和第三行高度固定,第二行高度自适应

<style>
.layout{
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
}
.layout > div {
  width: 100%;
}
.layout div:first-child{
  background: red;
  height: 100px;
}
.layout div:nth-child(2){
  background: yellow;
  flex-grow: 1;
}
.layout div:last-child{
  background: blue;
  height: 100px;
}
</style>

<div class="layout">
  <div></div>
  <div></div>
  <div></div>
</div>
  • 使用calc计算
.layout{
  width: 100%;
  height: 100vh;
}
.layout > div {
  width: 100%;
}
.layout div:first-child{
  background: red;
  height: 100px;
}
.layout div:nth-child(2){
  background: yellow;
  height: calc(100% - 200px);
}
.layout div:last-child{
  background: blue;
  height: 100px;
}
  • 使用绝对定位
.layout{
  width: 100%;
  height: 100vh;
  position: relative;
}
.layout > div {
  width: 100%;
}
.layout div:first-child{
  background: red;
  height: 100px;
}
.layout div:nth-child(2){
  background: yellow;
  position: absolute;
  z-index: 1;
  top: 100px;
  left: 0;
  right: 0;
  bottom: 100px;
}
.layout div:last-child{
  background: blue;
  height: 100px;
  position: absolute;
  z-index: 1;
  left: 0;
  bottom: 0;
}