# CSS 面试题

# 一、CSS 选择器

# 1.CSS2 选择器:

  • 标签选择器(div, h1, p)
  • id选择器(#myid)
  • 类选择器(.myclass)
  • 通配符选择器(*)
  • 后代选择器(li a)

# 2.CSS2 伪类选择器:

  • 伪类选择器(a:link/visited/hover/active)

# 3.CSS3 选择器:

空格 > +相邻兄弟选择器 ~ 通用选择器(查找后面所有)

# 4.结构伪类选择器:

  • 查找第几个:nth-child(n)
  • 查找同一类型第几个:nth-of-type
  • 查找唯一类型:only-of-type

# 5.属性选择器:

根据标签属性查找[attr-value]

  • :root 查找根元素 html 标签
  • :empty 查找空标签

# 6.目标伪类选择器:(表单)

  • :enabled 查找可以使用的标签
  • :disabled 查找禁止使用的标签
  • :checked 查找被选中的标签

# 7.伪元素选择器::selection设置选中文本内容的高亮显示(只能用于背景和文本颜色)

  • 否定伪类选择器 not()
  • 语言伪类选择器 lang(取值)

# 8.优先级(权重):

  • !important
  • 行内样式(1000) (在style属性里面写的样式)
  • id选择器(0100)#
  • 类选择器/属性选择器/伪类选择器(0010)
  • 标签选择器/伪元素选择器(0001)
  • 关系选择器/通配符选择器(0000)

!important > ID选择器 > 类选择器 > 标签选择器 > 通配符选择器

样式表的来源不同时,优先级顺序为:
内联样式 > 内部样式 > 外部样式 > 浏览器用户自定义样式 > 浏览器默认样式

# 9.可以继承的元素:

CSS 继承特性主要是文本方面

所有元素可继承:visibility 和 cursor。
块级元素可继承:text-indent 和 text-align。
列表元素可继承:list-style,list-style-type,list-style-position,list-style-image。
内联元素可继承:
letter-spacing(字体间距)
word-spacing(段落间距)
line-height(行高)
color(字体颜色)
font-family(字体种类)
font-size(字体大小)
font-style(字体样式)
font-variant(小型大写字母文本)
font-weight(字体粗细)
text-decoration(文本修饰)
text-transform(转换不同元素中的文本)
direction(文本方向)

# 二、CSS 盒子模型

一个 CSS 盒子从外到内可以分成四个部分:
margin(外边距),border (边框),padding(内边距/填充),content(内容)。

盒子模型

默认情况下,盒子的 width 和 height 属性只是设置 content(内容)的宽和高。

  • 盒子真正的宽是:内容宽度(width)+左右填充(padding)+左右边框(border)+左右外边距(margin)。
  • 盒子真正的高是:内容高度(height)+上下填充(padding)+上下边框(border)+上下外边距(margin)。

CSS 中的盒子模型包括: IE 盒子模型和标准的 W3C 盒子模型。

故在计算盒子的宽度时存在差异:

  • 标准盒模型:总宽度 = width+左右填充(padding)+左右边框(border)+左右外边距(margin)
    【width 指 content 部分的宽度】
  • 怪异盒模型:总宽度 = width+左右外边距(margin)
    【width 指 边框 (border)+填充 (padding)+内容 (content) 部分的宽度】

# 三、box-sizing 属性

box-sizing 规定两个并排的带边框的框.

  • content-box:盒子的宽高会变(width 不包括 padding 和 border)【标准盒模型】。
box-sizing: content-box;
  • border-box:盒子的宽高不变(width 包括 padding 和 border)【怪异盒模型】。
box-sizing: border-box;
  • inherit:继承父元素的 box-sizing 值。
box-sizing: inherit;

# 四、CSS 定位

# 1. 固定定位 fixed:脱离文档流,相对于浏览器可视区定位。

不占据空间,和其他元素重叠。
使用场景:浏览器页面滚动(不会移动)。

position: fixed;

# 2. 相对定位 relative:不脱离文档流,相对于原来的位置定位。

继续保留原来的位置,它会覆盖其他框。

position: relative;

# 3. 绝对定位 absolute:脱离文档流,相对于父级定位(拼爹型)。

不占据空间,和其他元素重叠。
父级有定位:以最近一级有定位父级为准定位。
父级无定位或无父级:以 body 为准定位。

position: absolute;
/* 
子绝父相:父级需要占有位置(相对定位),
子级不需要占有位置(绝对定位)。  */

# 4. 默认定位 static:默认值,又称为静态定位,元素出现在正常的流中。

position: static;

# 5. 粘性定位 sticky:

元素先按照普通文档流定位,然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。元素定位表现在跨越特定阈值前为相对定位,之后为固定定位。

position: sticky;

# 6. 继承 inherit:从父元素继承 position 属性的值。

position: inherit;

# 五、CSS 清除浮动的方法

高度塌陷:当所有的子元素浮动的时候,且父元素没有设置高度,这时父元素就会产生高度塌陷。

# 1. 设置高度法:

给父元素单独定义高度。

  • 优点:快速简单、代码少。
  • 缺点:无法进行响应式布局。

# 2. 空标签法:

在浮动元素后面加一个空标签。

.parent {
  clear: both;
  height: 0;
  overflow: hidden;
}

/* 很少使用这个方法 */
  • 优点:简单快速、代码少、兼容性高。
  • 缺点:增加空标签,不利于页面优化。

# 3. 父级定义 overflow: hidden 属性法:

.parent {
  overflow: hidden;
  /* zoom: 1;   针对 IE6 的兼容 */
}
/* 很少用这种方式 */
  • 优点:简单快速、代码少、兼容性高。
  • 缺点:超出部分被隐藏,布局时要注意。

# 4. ★万能清除法 :after :

给塌陷的元素添加伪对象,类型一般用 clearfix。

.clearfix: after {
  content: " ";         /* 内容为空 */
  height: 0;            /* 高度 0 */
  line-height: 0;       /* 行高为 0*/
  display: block;       /* 将文本转换为块级元素 */
  visibility: hidden;   /* 将元素隐藏 */
  clear: both;          /* 清除浮动 */
}

.clearfix {
  *zoom: 1;
/*  IE6、7 专用  */
}

/* ⚠️:★开发常用 */
  • 优点:写法固定、兼容性高。
  • 缺点:代码多

# 5. 父级定义 overflow: auto 属性法:

  • 优点:简单、代码少、兼容性好。
  • 缺点:内部宽高超过父级 div 时,会出现滚动条。

# 6. 双伪元素法:

(类型一般用:clearfix)

.clearfix: before,
.clearfix: after {
  content: " ";
  display: block;
  clear: both;   
}

.clearfix {
  *zoom: 1;
}

/* ⚠️注意:很少用这种方式,改良版虽然比较简便,但是不严谨! */

# 六、水平垂直居中的方法

# 1.垂直居中:

  • 纯文字类实现居中:
    line-height: 跟盒子本身的高度相等;
    

# 2.水平居中:

  • 对于行内元素和文字:
    把 text-align: center; 给行内元素的父盒子。
    <div class="box-a">
      <span>123</span>
    </div>
    
    .box-a {
      text-align: center;  /* 只实现水平居中 */
    }
    
  • 对于确定宽度的块级元素:
    width 和 margin。
    width: 100px;
    margin: 0 auto;
    <div class="box-b">123</div>
    
    .box-b {
      width: 100px;
      margin: 0 auto;
    }
    

# 3.水平垂直居中:

  • 对于确定宽度的块级元素:

    • (1) 子绝父相 和 margin-left、margin-top
      position: relative;
      position: absolute;
      margin-left: (父width - 子width) / 2;
      margin-top: (父height - 子height) / 2;
    <div class="box-a">
      <div class="box-b">123</div>
    </div>
    
    .box-a {
      position: relative;
      width: 200px;
      height: 200px;
      background-color: green;
    }
    .box-b {
      position: absolute;
      width: 100px;
      height: 100px;
      margin-left: 50px;
      margin-top: 50px;
      background-color: yellow;
    }
    
    • (2) 子绝父相 和 left、top、-margin-left、 -margin-top(left、top都是宽高的一半)
    <div class="box-c">
      <div class="box-d">123</div>
    </div>
    
    .box-c {
      position: relative;
      width: 200px;
      height: 200px;
      background-color: green;
    }
    .box-d {
      position: absolute;
      width: 100px;
      height: 100px;
      left: 50%;   
      top: 50%;
      margin-left: -50px; /* 本身宽的一半 */    
      margin-top: -50px;  /* 本身高的一半 */
      background-color: yellow;
    }
    
  • 对于宽度未知的块级元素:

    • (1) 子绝父相 和 transform
      position: relative;
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      <div class="box-a">
        <div class="box-b">123</div>
      </div>
      
      .box-a {
        position: relative;
        width: 400px;
        height: 400px;
        background-color: yellow;
      }
      .box-b {
        position: absolute;
        transform: translate(-50%, -50%); 
        width: 200px;
        height: 200px;
        left: 50%;   
        top: 50%;
        background-color: green;
      }
      
      • (2) flex 布局:
        display: flex;
        justify-content: center;
        align-items: center; 三个都给父盒子
      <div class="box-c">
        <div class="box-d">123</div>
      </div>
      
      .box-c {
        display: flex;
        justify-content: center;
        align-items: center;
        background-color: yellow;
      }
      .box-d {
        background-color: green;
      }
      

# 七、隐藏页面中某个元素的方法

  1. opacity:0; 该元素隐藏起来了,但不会改变页面布局,如果绑定 click 事件,点击该区域,能触发事件。

  2. visibility:hidden; 该元素隐藏起来了,但不会改变页面布局,不会触发该元素绑定的事件 ,隐藏对应元素,在文档布局中仍保留原来的空间(重绘)。

  3. display:none; 把元素隐藏起来,并且会改变页面布局。在文档布局中不再分配空间(回流+重绘)。

# 八、回流和重绘

# 1.回流和重绘

(1)回流(Reflow):引起 DOM 树结构变化,改变页面布局的过程。

(2)重绘(Repaint):不影响页面布局,只跟样式有关的元素进行重新绘制的操作。

! 注意:回流必引起重绘,而重绘不一定会引起回流。

# 2.减少回流和重绘的方法

(1)CSS 中避免回流和重绘:

  • 尽量在 DOM 树的最末端改变 class
  • 避免设置多层内联样式
  • 动画效果应用到 position 设置为 absolute 或者 fixed 的元素上
  • 避免使用 table 布局
  • 使用 CSS3 硬件加速,可以让 transform、opacity、filters 等动画不会引起重绘

(2)JS 避免回流和重绘:

  • 避免使用 JS 一个样式修改完接着下一个样式,最好一次性更改 CSS 样式,或者将样式定义好 class
  • 避免频繁操作 DOM,使用文档片段创建子树,然后再拷贝到文档中
  • 先隐藏元素,进行修改后再显示该元素,因为 display:none 上的DOM操作不会引起回流和重绘
  • 避免循环读取 offsetleft 等属性,在循环之前把他们存起来
  • 对于复杂的动画效果,使用绝对定位让其脱离文档流,否则会引起父元素及后续元素大量回流

# 3.Vue 的 v-if 与 v-show 区别

(1)v-if:是通过控制 DOM 节点的存在与否来控制元素的显隐。

(2)v-show:是通过设置 DOM 元素的 display 样式,block为显示,none 为隐藏。

如需要频繁切换建议使用 v-show,如在运行时条件很少改变,则用 v-if。

# 九、BFC (块级格式上下文)

# 1.BFC 的概念

BFC 是 CSS 布局的一个概念,是一个独立的渲染区域,块级格式上下文。

# 2.如何创建BFC?

  • 根元素,即 HTML 元素
  • float 的值不为 none
  • overflow 的值不为 visible
  • position 的值为 absolute 或 fixed
  • display 的值为 inline-block、table-cell、table-caption

# 3.BFC的使用场景

  • 去除边距重叠现象
  • 清除浮动(让父元素的高度包含子浮动元素)
  • 避免某元素被浮动元素覆盖
  • 避免多列布局由于宽度计算四舍五入而自动换行

# 十、页面布局

# 1.Flex 布局

原理:就是通过给父盒子添加 flex 属性,来控制子盒子的位置和排列方式。

(1)容器的属性:

  • flex-direction: 子元素排列方式(主轴排列方式)。
.box {
flex-direction: row | row-reverse | column | column-reverse;
}

/* 
row: 默认值,从左到右,水平方向
row-reverse:从右到左,水平
column:从上往下,垂直方向
column-reverse:从下往上,垂直
*/
  • flex-wrap: 子元素超出父元素时是否换行。
.box {
  flex-wrap: nowrap | wrap | wrap-reverse;
}

/*
nowrap:默认值,不换行
wrap:换行,第一行在上方
wrap-reverse:换行,第一行在下方
*/
  • flex-flow: flex-direction 和 flex-wrap 的简写形式。
.box {
  flex-flow: <flex-direction>|| <flex-wrap>;
}
  • justify-content: 水平主轴对齐方式。
.box {
  justify-content: flex-start | flex-end | center | space-between | space-around;
}

/* 
flex-start:默认值,左对齐
flex-end:右对齐
center:居中
space-between:两端对齐,项目之间的间隔都相等
space-around:每个项目两侧的间隔都相等,项目之间的间隔比项目与边框的间隔大一倍。
*/
  • align-items: 竖直轴线对齐方式。
.box {
  align-items: flex-start | flex-end | center | baseline | stretch;
}

/* 
stretch:默认值,如项目无高度或auto,会占满整个容齐的高度
flex-start:对齐上边
flex-end:对齐下边
center:竖直轴的中心对齐(垂直对齐)
baseline:项目的第一行文字的基线对齐(所有的文字在同一水平)
*/
  • align-content: 多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
.box {
  align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}

/* 
stretch:默认值,轴线占满整个交叉轴(垂直方向的轴)
flex-start:交叉轴的起点对齐
flex-end:交叉轴的终点对齐
center:交叉轴的中心对齐
space-between:与交叉轴两端对齐,轴线之间的间隔平均分布
space-around:每根轴线两侧的间隔都相等。轴线之间的间隔比轴线与边框的间隔大一倍
*/

(2)项目的属性

  • order:排列顺序。数值越小,排列越靠前,默认为0。
.item {
  order: <integer>;
}
  • flex-grow:放大比例,默认为0,即如果存在剩余空间,也不放大。
.item {
  flex-grow: <number>; /* default 0 */
}
  • flex-shrink:缩小比例,默认为1,即如果空间不足,该项目将缩小。
.item {
  flex-shrink: <number>; /* default 1 */
}
  • flex-basis:在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
.item {
  flex-basis: <length> | auto; /* default auto */
}
  • flex:是 flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
/* 
该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)
*/
  • align-self:允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
/* 
除了auto,其他都与align-items属性完全一致
*/

# 2.Rem 布局

首先 Rem 相对于根(html)的 font-size 大小来计算。简单的说它就是一个相对单例,如:font-size:10px; 那么(1rem = 10px)

  • 优点:可以快速适用移动端布局,字体,图片高度。
  • 缺点:
    ① 目前 ie 不支持,对 pc 页面来讲使用次数不多;
    ② 数据量大:所有的图片,盒子都需要我们去给一个准确的值,才能保证不同机型的适配;
    ③ 在响应式布局中,必须通过 js 来动态控制根元素 font-size 的大小。也就是说 css 样式和 js 代码有一定的耦合性,且必须将改变 font-size 的代码放在 css 样式之前。

# 3.百分比布局

通过百分比(%)单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。

  • 缺点:
    (1)计算困难。
    (2)各个属性中如果使用百分比,相对父元素的属性并不是唯一的。造成我们使用百分比单位容易使布局问题变得复杂。

# 4.浮动布局

(1)浮动:

  • 脱离标准普通流的控制(浮)移动到指定位置(动),俗称脱标。
  • 浮动的盒子不再保留原先的位置。

(2)特点:

  • 任何元素都可以浮动。不管原先是什么模式的元素,添加浮动之后具有行内块元素相似的特点。
  • 如果行内块元素有了浮动,则不需要转换 块级\行内元素就可以直接给高度和宽度。

(3)缺点:
最明显的缺点就是浮动元素一旦脱离了文档流,就无法撑起父元素,会造成父级元素高度塌陷。

(4)可以解决高度塌陷问题:

/* ① 可以为父元素定义上边框 */
border: 1px solid transparent;
/* ② 可以为父元素定义内边距 */
padding: 1px;
/* ③ 可以为父元素添加 overflow: hidden; */
overflow: hidden;

# 5.三栏布局方式

两边固定中间自适应。

  1. margin 负值法:左右两栏均左浮动,左右两栏采用负的 margin 值。
    中间栏被宽度为 100%的浮动元素包起来
  2. 自身浮动法:左栏左浮动,右栏右浮动,中间栏放最后
  3. 绝对定位法:左右两栏采用绝对定位,分别固定于页面的左右两侧,
    中间的主体栏用左右 margin 值撑开距离。
  4. flex 左右固定宽 中间 flex:1
  5. 网格布局
  6. table 布局

# 6.Px,rem,em 的区别

Px 是绝对长度单位,像素 px 是相对于显示器屏幕分辨率来说的。
em 相对长度单位,相对于当前对象内文本的字体尺寸。
em 的值并不是固定的
em 会继承父级元素的字体大小(参考物是父元素的 font-size)
em 中所有的字体都是相对于父元素的大小决定的
rem 相对于 html 根元素的 font-size
1em=1rem=16px 在 body 中加入 font-size:62.5%
这样直接就是原来的 px 数值除以 10 加上 em 就可以。

Rem 缺点:
比如:小说网站,屏幕越小的移动设备如果用了 rem 肯定文字就越小,就会导致看文章的时候特别费眼。

# 十一、Margin 和 padding 的使用场合

Margin 外边距: 自身边框到另一个边框之间的距离。
Padding 内边距: 自身边距到自身内容之间的距离。
当需要在 border 外侧添加空白时用 margin,当需要在 border 内侧添加空白时用 padding。

# 十二、双边距重叠问题(外边距折叠)

多个相邻(兄弟或者父子关系)普通流的块元素垂直方向 marigin 会重叠。
折叠的结果为:

  • 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大值。
  • 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
  • 两个外边距一正一负时,折叠结果是两者的相加的和。

# 十三、CSS3 新属性

  • 在布局方面新增了: flex 布局
  • 在选择器方面新增了: 例如first-of-type,nth-child 等选择器
  • 在盒模型方面添加了: box-sizing 来改变盒模型
  • 在动画方面增加了: animation,2d 变换,3d 变换
  • 在颜色方面添加:透明,rbga
  • 在字体方面:允许嵌入字体和设置字体阴影
  • 媒体查询:扩展了 media 属性,就是根据不同的媒体类型设置不同的 css 样式,达到自适应的目的。

# 十四、CSS3 新增的特性

# 1. 边框:

  • border-radios: 添加圆角边框
  • border-shadow:给边框添加阴影(水平位移,垂直位移,模糊半径,阴影尺寸,阴影颜色,insetr(内/外部阴影))
  • border-image:设置边框图像
  • border-image-source: 边框图片的路径
  • border-image-slice: 图片边框向内偏移
  • border-image-width: 图片边框的宽度
  • border-image-outset: 边框图像区域超出边框的量
  • border-image-repeat: 图像边框是否平铺(repeat 平铺 round 铺满 stretch 拉伸)

# 2. 背景:

  • background-size: 背景图片尺寸
  • background-origin: 规定background-position属性相对于什么位置定位
  • background-clip: 规定背景的绘制区域(padding-box,border-box,content-box)

# 3. 渐变:

  • linear-gradient( )线性渐变
  • radial-gradient( )径向渐变

# 4. 文本效果:

  • word-break:定义如何换行
  • word-wrap:允许长的内容可以自动换行
  • text-overflow:指定当文本溢出包含它的元素,应该干啥
  • text-shadow:文字阴影(水平位移,垂直位移,模糊半径,阴影颜色)

# 5. 转换:

  • transform: 应用于 2D3D 转换,可以将元素旋转、缩放、移动、倾斜
  • transform-origin: 可以更改元素转换的位置,(改变 xyz 轴)
  • transform-style: 指定嵌套元素怎么样在三位空间中呈现

# 6. 2D 转换方法:

  • rotate: 旋转 translate(x,y)指定元素在二维空间的位移 scale(n) 定义缩放转换。

# 7. 3D 转换方法:

  • perspective:(n)为 3D 转换 translate rotate scale。

# 8. 过渡:

  • transition-proprety: 过渡属性名
  • transition-duration: 完成过渡效果需要花费的时间
  • transition-timing-function: 指定切换效果的速度
  • transition-delay: 指定什么时候开始切换效果

# 9.动画:

  • animation-name: 为@keyframes 动画名称
  • animation-duration: 动画需要花费的时间
  • animation-timing-function: 动画如何完成一个周期
  • animation-delay: 动画启动前的延迟间隔
  • animation-iteration-count: 动画播放次数
  • animation-direction: 是否轮流反向播放动画

# 十五、CSS3 动画和 JS 动画的差异性

渲染线程分为 main thread 和 compositor thread,如果 css 动画只改变 transform 和 opacity ,
这时整个 CSS 动画得以在 compositor trhead 完成(而 JS 动画则会在 main thread 执行, 然后出发 compositor thread 进行下一步操作),特别注意的是如果改变 transform 和 opacity 是不会 layout 或者 paint 的。
区别: 功能涵盖面,JS 比 CSS 大
实现/重构难度不一,CSS3 比 JS 更加简单,性能跳优方向固定对帧速表现不好的低版本浏览器,CSS3 可以做到自然降级
CSS 动画有天然事件支持 CSS3 有兼容性问题。

# 十六、CSS3 中对溢出的处理

cnkOhu
text-overflow 属性,值为 clip 是修剪文本;
ellipsis 为显示省略符号来表被修剪的文本;
string 为使用给定的字符串来代表被修剪的文本。

# 十七、CSS 预处理 sass、less

Sass 和 less 都是 CSS 预处理器,是 CSS 上的一种抽象层,是一种特殊的语法,
最终会编译成 CSS,less 是一种动态样式语言,给 CSS 赋予了动态。
语言的特性,比如:变量,继承,嵌套。Less 既可以在客户端运行,也可以在服务端运行(需要借助 node)。

# 十八、用 CSS 实现三角符号

<div></div>
/* 记忆口诀:盒子宽高均为零,三面边框皆透明 */
div:after {
  position: absolute;
  width: 0px;
  height: 0px;
  content: " ";
  border-right: 100px solid transparent;
  border-top: 100px solid #ff0;
  border-left: 100px solid transparent;
  border-bottom: 100px solid transparent;
}

# 十九、画一条 0.5px 的线

采用 meta viewport 的方式:

<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>

采用 border-image 的方式。
采用 transform: scale() 的方式。

# 二十、怎么实现标签的禁用

添加 disabled 属性。