# CSS 盒模型

CSS 中有两种盒模型:标准盒模型IE盒模型

标准盒模型:

在标准和模型中,如果给盒子设置 width 和 height,实际设置的是 content 内容区域的宽和高。内边距 padding 和边框 border 加上设置的宽高一起决定了盒子的大小。

IE盒模型

在IE盒模型中,如果个盒子设置 width 和 height,那么盒子的大小就是设置的宽高值,如果盒子设置了内边距 padding 和边框 border,那么内容的大小实际是盒子的大小减去内边距和边框后的值。

差异比较举例:

.box {
  width: 100px;
  height: 100px;
  margin: 25px;
  padding: 20px;
  border: 15px solid red;
}

标准盒模型图示:

标准盒模型

盒子的宽度 = width + padding-left/right + border-left/right(100+20+20+15+15=170)

内容的宽度 = width(100)

IE盒模型图示:

IE盒模型

盒子的宽度 = width(100)

内容的宽度 = width + padding-left/right + border-left/right(100-20-20-15-15=30)

CSS 如何设置:

/* 标准盒模型 */
box-sizing: content-box;
/* IE盒模型 */
box-sizing: border-box;

# BFC(块格式化上下文)

块格式化上下文(Block Formatting Context,BFC)是 Web 页面的可视 CSS 渲染的一部分,是块级盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。可以在页面中创建一个独立的容器,容器里面的字元素不会影响到外面的元素。

触发BFC的条件:

  • 根元素(<html>)
  • 浮动元素(float 值不为 none)
  • 绝对定位元素(position 值为 absolute 或 fixed )
  • display 值为 inline-block/table/table-cell/table-caption/table-row/flex/inline-flex
  • overflow 值不为 visibleclip 的块元素
  • 多列容器 grid 布局元素的直接子元素

BFC作用:

  • 清除浮动
    • 高度塌陷问题,在通常情况下父元素的高度会被子元素撑开,如果其子元素为浮动元素所以父元素发生了高度坍塌,上下边界重合,这时就可以用BFC来清除浮动了
  • 分属于不同BFC时,可以防止margin重叠
    • 在标准文档流中,块级标签之间竖直方向的margin会以大的为准
  • 阻止元素被浮动元素覆盖
    • 左右两个元素,左侧块级元素发生了浮动,所以和右侧未发生浮动的块级元素不在同一层内,所以会发生div遮挡问题。可以给右侧元素添加 overflow: hidden,触发BFC来解决遮挡问题。

# 设置元素浮动后,该元素 display 值时多少?

元素设置 float 浮动后,将自动变为 display: block

# 说一说 CSS 中的定位 position

  • static(默认)

    该元素指定元素使用正常的布局行为,即元素在文档常规流中当前布局的位置。此时设置 toprightbottomleftz-index 无效。

  • relative

    不脱离文档流。该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白),它原本所占的空间仍保留。在使用相对定位时,无论是否进行移动,元素仍然占据原来的空间。因此,移动元素会导致它覆盖其它框。

  • absolute

    元素会被移出正常文档流,并不为元素预留空间,通过指定元素相对与最近的非 static 定位祖先元素的偏移,来确定元素的位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。

  • fixed

    元素会被移出正常文档流,通过制定元素相对与屏幕视口的位置来指定元素位置。元素在屏幕滚动时不会发生位置改变。当祖先元素的 transformperspectivefilter 属性非 none 时,容器由窗口改为改祖先元素。

  • sticky

    元素根据正常文档流进行定位,然后相对它的最近滚动祖先最新块级组件进行偏移。注意,一个 sticky 元素会“固定”在离它最近的一个拥有“滚动机制”的祖先上(当该祖先的overflow 是 hidden, scroll, auto, 或 overlay时),即便这个祖先不是最近的真实可滚动祖先。

# 说一说 CSS 中隐藏元素的方法

  • display: none 不显示对应的元素,在文档布局中不占居空间。涉及 DOM 结构,产生回流(reflow)重绘(repaint)
  • visibility: hidde 元素不可见但存在,保留空间,不影响 DOM 结构。只产生 重绘(repaint),但不可触发绑定事件。
  • opacity: 0 元素不可见,透明度为0,文档布局中保留其空间,不影响 DOM 结构。只产生重绘(repaint),如果该元素已经绑定一些事件,如click事件,那么点击该区域,也能触发点击事件的

# CSS 中伪类和伪元素是什么,有什么区别

伪类: 伪类是选择器的一种,它用于选择处于特定状态的元素。比如说,当用户悬停在指定的元素时,我们可以通过:hover来描述这个元素的状态。

伪元素: 伪元素用于创建一些不在文档树中的元素,并为其添加样式。

两者区别:

伪元素的操作对象是新生成的dom元素,而不是原来dom结构里就存在的;而伪类恰好相反,伪类的操作对象是原来的dom结构里就存在的元素。

伪元素是使用单冒号还是双冒号

CSS3规范中的要求使用双冒号(::)表示伪元素,以此来区分伪元素和伪类,比如::before和::after等伪元素使用双冒号(:😃,:hover和:active等伪类使用单冒号(😃。除了一些低于IE8版本的浏览器外,大部分浏览器都支持伪元素的双冒号(::)表示方法。

伪类 伪元素

  • 从属关系区别
    • @import是 CSS 提供的语法规则,只有导入样式表的作用;
    • link是HTML提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等
  • 加载顺序区别
    • 加载页面时,link标签引入的 CSS 被同时加载
    • @import引入的 CSS 将在页面加载完毕后被加载
  • 兼容性区别
    • @import是 CSS2.1 才有的语法,故只可在 IE5+ 才能识别
    • link标签作为 HTML 元素,不存在兼容性问题
  • DOM可控性区别
    • 可以通过 JS 操作 DOM ,插入link标签来改变样式
    • 由于DOM方法是基于文档的,无法使用@import的方式插入样式

# 清除浮动有哪些方法

  • clear清除浮动,在浮动元素下方添加空div,并给该元素写css样式
    • { clear:both; height:0; overflow:hidden; }
  • 给浮动元素父级设置高度
  • 父级设置成inline-block,其margin: 0 auto居中方式失效
  • 给父级添加overflow:hidden 清除浮动方法
  • after伪类 清浮动
.clearfix::after {
  content:".";
  clear:both;
  display:block;
  height:0;
  overflow:hidden;
  visibility:hidden;
}
.clearfix {
  zoom: 1;
}

# CSS 中权重和优先级

权重,从大到小:

  1. !import 无限大
  2. 行内样式 +1000
  3. id选择器 +100
  4. 一个属性选择器、class或者伪类 +10
  5. 一个元素选择器,或者伪元素 +1
  6. 通配符 +0

权重

  • 常用选择器权重优先级:!important > id > class > tag
  • 如果两条样式都使用!important,则权重值高的优先级更高
  • 在css样式表中,同一个CSS样式你写了两次,后面的会覆盖前面的
  • 样式指向同一元素,权重规则生效,权重大的被应用
  • 样式指向同一元素,权重规则生效,权重相同时,就近原则生效,后面定义的被应用
  • 样式不指向同一元素时,权重规则失效,就近原则生效,离目标元素最近的样式被应用

# position 跟 display、overflow、float 这些特性相互叠加后会怎么样?

display 属性规定元素应该生成的块的类型

position 属性规定元素的定位类型

float 属性是一种布局方式,定义元素在哪个方向浮动

类似于优先级机制:position:absolute/fixed优先级最高,有他们在时,float不起作用,display值需要调整。float 或者 absolute 定位的元素,只能是块元素或表格。

# li 与 li 之间有看不见的空白间隔是什么原因引起的?有什么解决办法?

li 元素排列会受到中间空白(回车空格)等的影响,因为空格也属于字符,这些空白也会被应用样式,占据空间,所以会有间隔,把字符大小设为0,就没有空格了。

解决方法:

  • 可以将代码全部写在一排
  • 浮动li中float:left
  • 可以将 ul{ letter-spacing: -4px;}; li{letter-spacing: normal;}

# style 标签写在 body 后与 body前有什么区别?

页面加载自上而下 当然是先加载样式。

写在 body 标签后由于浏览器以逐行方式对HTML文档进行解析,当解析到写在尾部的样式表(外联或写在 style 标签)会导致浏览器停止之前的渲染,等待加载且解析样式表完成之后重新渲染,在windows的IE下可能会出现 FOUC 现象(即样式失效导致的页面闪烁问题)

# 行内元素与块级元素有什么区别

行内元素:

  • 行内元素不换行
  • 行内元素不可以设置大小
  • 行内元素的大小由内容绝定

块级元素:

  • 块级元素独立成行
  • 块级元素可以设置大小
  • 块级元素如果不设置宽度,宽度会自适应其父级宽度

# 解决 img 图片自带边距的问题

谷歌中这样是解释的:

图片底部的空隙实际上涉及行内元素的布局模型,图片默认的垂直对齐方式是基线,而基线的位置是与字体相关的。所以在某些时候,图片底部的空隙可能是 2px,而有时可能是 4px 或更多。不同的 font-size 应该也会影响到这个空隙的大小。

解决办法: 最优的解决办是定义vertical-align,注:定义vertical-align为middle时在IE6中大概还有一像素的顶边距,最好为top或bottom。当然还有种极端解决办法大家可以试试就是将 父容器的字体大小为零,font-size:0

(1)转化成(行级)块元素

display: block

(2)浮动,浮动后的元素默认可以转化为块元素(可以随意设置宽高属性)

float: left;

(3)给 img 定义 vertical-align(消除底部边距)

img{
    border: 0;
    vertical-align: bottom;
}

(4)将其父容器的font-size 设为 0

(5)给父标签设置与图片相同的高度

# 标签上 title 属性与 alt 属性的区别是什么

  • title: 鼠标放入时提示的文字
  • alt: 图片路径出错时,提示文字

# CSS 中有哪些单位

单位 描述
px px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。
em em是相对长度单位。相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸。一般浏览器字体大小默认为16px,则2em == 32px
rem rem作用于非根元素时,相对于根元素字体大小;rem作用于根元素字体大小时,相对于其出初始字体大小
vh viewpoint height,视窗高度,1vh=视窗高度的1%
vw viewpoint width,视窗宽度,1vw=视窗宽度的1%
vmin vw和vh中较小的那个
vmax vw和vh中较大的那个

rem与em有什么区别呢?区别在于使用rem为元素设定字体大小时,仍然是相对大小,但相对的只是HTML根元素。

# 为什么要对 CSS 样式进行初始化

因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。

# CSS优化、提高性能的方法有哪些

  • 尽量将样式写在单独的css文件里面,在head元素中引用
    • 内容和样式分离,易于管理和维护
    • 减少页面体积
    • css文件可以被缓存、重用,维护成本降低
  • 避免使用复杂的选择器,层级越少越好 建议选择器的嵌套最好不要超过三层
  • 利用CSS继承减少代码量
  • 资源压缩
  • 避免 !important,可以选择其他选择器

# 说一说回流(重排)和重绘

# 回流

DOM 的修改引发了 DOM 几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,浏览器需要重新计算元素的几何属性(其他元素的几何属性和位置也会因此受到影响),然后再将计算的结果绘制出来。这个过程就是回流(也叫重排)。

由本身的大小宽高改变,引发 局部全局 的排版,会引发回流或局部回流

全局范围:从根节点 html 开始对整个渲染树进行重新布局。 局部范围:对渲染树的某部分或某一个渲染对象进行重新布局

# 重绘

对 DOM 的修改导致了样式的变化、却并未影响其几何属性(比如修改了颜色或背景色)时,浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式。这个过程叫做重绘。

只改变外观、风格,不影响布局,会引发重绘

# 触发回流的时机

  • 添加或删除可见的DOM元素
  • 元素的位置发生变化
  • 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
  • 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代
  • 页面一开始渲染的时候(这避免不了)
  • 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)

特定属性值:

offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、 scrollHeight、clientTop、clientLeft、clientWidth、clientHeight

这些属性有一个共性,就是需要通过即时计算得到。因此浏览器为了获取这些值,也会进行回流。

getComputedStyle 方法,原理是一样的

# 触发重绘的时机

触发回流一定会触发重绘

  • 颜色的修改
  • 文本方向的修改
  • 阴影的修改

# 如何减少触发回流和重绘

  • 如果想设定元素的样式,通过改变元素的 class 类名 (尽可能在 DOM 树的最里层)
  • 避免设置多项内联样式
  • 应用元素的动画,使用 position 属性的 fixed 值或 absolute
  • 避免使用 table 布局,table 中每个元素的大小以及内容的改动,都会导致整个 table 的重新计算
  • 对于那些复杂的动画,对其设置 position: fixed/absolute,尽可能地使元素脱离文档流,从而减少对其他元素的影响
  • 使用css3硬件加速,可以让transformopacityfilters这些动画不会引起回流重绘
  • 避免使用 CSS 的 JavaScript 表达式