HTML+CSS面试题
参考:https://juejin.cn/post/7061588533214969892#heading-25
1.1 如何理解语义化
- 代码结构清晰,方便阅读,有利于团队合作开发。
- 方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以语义的方式来渲染网页。
- 有利于搜索引擎优化(SEO),也就是有助于爬虫抓取更多的有效信息,因为爬虫是依赖于标签来确定上下文和关键字的权重。
1.2 script标签中defer和async的区别
明确defer和async是script标签中的属性。
- script: 阻碍html解析,script脚本加载完后才会进行html解析。
- async script: 可能阻碍html解析,边解析html边加载script脚本。
- defer script:不会阻碍html解析,等待html解析完成之后再加载script脚本。
1.3 从浏览器地址栏输入url到请求返回发生了什么
- 输入url后解析出对应的协议,主机,端口,路径等信息,并构造一个http请求。
- DNS域名解析。
- TCP连接,也就是三次握手的过程,第一次确认客户端发送能力,第二次确认服务端接收和发送能力,第三次确认客户端接收能力。缺少则容易丢包。
- 客户端发送http请求。
- 服务器处理请求,并发送http报文。
- 客户端接收http报文,并由游览器渲染页面。
- 断开tcp连接。
1.4 盒模型的认识
CSS3中的盒模型有以下两种,标准和模型和IE(替代)盒模型。
两种盒模型都是由 content+padding+border+margin 构成。
其中盒子的大小由 content+padding+border 决定,但是盒模型的宽高计算范围会根据盒模型的不同会有区别。
- 标准盒模型:只包含 content。(默认)
- IE(替代)盒模型:包含 conten+padding+border。
如果需要改变盒模型的宽高计算,则需要使用 box-sizing: border-box; 转换为IE(替代)盒模型,实际效果会保证盒子内的东西不会撑开盒子,只会导致 padding+border 发生响应式变化。
1.5 css选择器和优先级
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RMYdewln-1658115160695)(evernotecid://BE9DEFAA-6BBE-48DD-B45E-993AC7B26341/appyinxiangcom/36368386/ENResource/p326)]@w=600
样式优先级:!important > style > id > class, 如果涉及多类型选择器作用于同一个元素的作用优先级判断,则会按照如下的一个优先级进行作用。
述文章中核心内容:
优先级是由 A 、B、C、D 的值来决定的,其中它们的值计算规则如下:
- 如果存在内联样式,那么 A = 1,否则 A = 0 ;
- B 的值等于 ID选择器(#id) 出现的次数;
- C 的值等于 类选择器(.class) 和 属性选择器(a[href=“https://example.org”]) 和 伪类(:first-child) 出现的总次数;
- D 的值等于 标签选择器(h1,a,div) 和 伪元素(::before,::after) 出现的总次数。
如果样式优先级相等,取后面出现的样式。
1.6 重排(reflow)和重绘(repaint)的理解
重排:无论通过什么方式影响了元素的几何信息(元素在视口内的位置和尺寸大小),游览器需要重新计算元素在视口内的几何属性,这个过程叫做重排。
重绘:通过构造渲染树和重排阶段(回流阶段),可以知道哪些节点上可见的,以及可见节点的样式和具体的几何信息,接下来就可以将渲染树的每个节点都转化为屏幕上的实际像素,这个阶段就叫做重绘。
如何减少重排和重绘?
推荐文章:
腾讯 IVWEB 团队写的文章:你真的了解重排(回流)和重绘吗
- 最小化重绘和重排,比如样式的集中改变,使用添加新样式类名 .class 和 cssText 。
- 批量操作DOM,可以将类属性存入到一个临时的类变量,等需要再去调取使用;又比如利用 document.createDocumentFragment() 来添加要被添加的节点,待处理完后在插入到实际的DOM中。
- 使用 absolute 或 fixed 使元素脱离文档流,这在制作复杂的动画时对性能的影响比较明显。
- 开启GPU加速,利用 css 属性 transform 、will-change 等,通过该属性去改变元素位置信息,比使用定位去改变 top, left 等更加高效,因为使用 transform 不会触发重排或重绘,它会使游览器为元素单独创建一个GPU图层,这样会使动画元素在一个独立的层中进行渲染,当元素的内容没有改变,就没有必要进行重绘。
1.7 BFC的认识
BFC是块级格式上下文,每个元素都被定义为矩形的盒子,盒子的布局会受到尺寸,定位,盒子的子元素或兄弟元素,视口尺寸等因素影响。
为了处理这些影响,进行页面元素渲染,则需要有一个游览器计算的规则,计算规则是由视觉格式化模型的东西定义的,BFC来自这个概念,它是css视觉渲染的一部分,用于决定块级盒子的布局及浮动相互影响范围的一个区域。
BFC 具有的一些特性:
- 块级元素会在垂直方向一个接一个的排列,和文档流的排列方式一致。
- 在 BFC 中上下相邻的两个容器的 margin 会重叠,创建新的 BFC 可以避免外边距重叠。
- 计算 BFC 的高度时,需要计算浮动元素的高度。
- BFC 区域不会与浮动的容器发生重叠。
- BFC 是独立的容器,容器内部元素不会影响外部元素。
- 每个元素的左 margin 值和容器的左 border 相接触。
利用这些特性,我们可以解决以下问题:
- 利用 4 和 6 ,我们可以实现三栏(或两栏)自适应布局。
- 利用 2 ,我们可以避免 margin 重叠问题。
- 利用 3 ,我们可以避免高度塌陷。
创建BFC的方式:
- 绝对定位元素(position 为 absolute 或 fixed )。
- 行内块元素,即 display 为 inline-block 。
- overflow 的值不为 visible 。
1.8 三栏布局的实现
经典的三栏布局也就是 圣杯布局 和 双飞翼布局 的实现。
圣杯布局:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>圣杯布局(经典三分栏布局)</title>
<style>
#container {
height: 500px;
padding-left: 200px;
padding-right: 200px;
background-color: aqua;
overflow: auto;
}
#container div {
float: left;
}
.main {
width: 100%;
height: 100%;
background-color: rgb(255, 255, 0);
}
.left {
width: 200px;
height: 100%;
position: relative;
left: -200px;
margin-left: -100%;
background-color: rgb(255, 0, 0);
}
.right {
width: 200px;
height: 100%;
margin-right: -200px;
background-color: rgb(0, 123, 255);
}
.clearfix::after {
content: "";
display: block;
height: 0;
clear: both;
visibility:hidden;
}
</style>
</head>
<body>
<script>
/**
* 圣杯布局 (浮动 + 相对定位 + margin left right 负值运用)
* - 父盒子通过padding-left padding-right分割三个区域,自身使用清除浮动样式,并给子元素浮动样式
* - 优先渲染中间区域,需要中间区域样式提前到左右区域样式之前,中间区域需要自适应 width:100%
* - 左边区域样式 通过相对定位,left给负值+自身宽度 ,以及marging-left: 负值+100%
* - 右边区域margin-right:负值+自身宽度
*
* 圣杯布局优先渲染中间区域且是自适应宽度,margin 负值发生的位移是相对父元素的, 也就是指代父元素某边减少对应的宽高值或指子元素向某个方向移动对应的宽高值。
* 圣杯布局和双飞翼布局的目的:实现栏布局,两侧内容固定,中间内容随着宽度自适,并优先渲染,一般用于pc网页。
*/
</script>
<!-- 圣杯布局 padding实现 因为html结构是父盒子包裹左中右三个字元素 -->
<div id="container" class="clearfix">
<div class="main"></div>
<div class="left"></div>
<div class="right"></div>
</div>
</body>
</html>
双飞翼布局:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>双飞翼布局(经典三分栏布局)</title>
<style>
#container {
float: left;
width: 100%;
height: 500px;
background-color: aqua;
}
.main {
height: 500px;
margin-left: 200px;
margin-right: 200px;
background-color: #f2ff00;
}
.left {
float: left;
width: 200px;
height: 500px;
margin-left: -100%;
background-color: red;
}
.right {
float: left;
width: 200px;
height: 500px;
margin-left: -200px;
background-color: rgb(0, 128, 255);
}
</style>
</head>
<body>
<script>
/**
* 双飞翼布局 (浮动 + margin-letf 负值运用)
* - 父盒子定义明确的高度和自适应的宽度width: 100%,自身使用浮动样式
* - 优先渲染中间区域,需要中间区域样式提前到左右区域样式之前,中间区域需要使用magrin left right,分割出三个区域
* - 左边区域样式 浮动 以及marging-left: 负值+100%
* - 右边区域 浮动 以及margin-letf:负值+自身宽度 (给了浮动 注意都是从右往左移动应该是margin-left给负值)
*
* 圣杯布局优先渲染中间区域且是自适应宽度,margin 负值发生的位移是相对父元素的, 也就是指代父元素某边减少对应的宽高值或指子元素向某个方向移动对应的宽高值。
* 圣杯布局和双飞翼布局的目的:实现栏布局,两侧内容固定,中间内容随着宽度自适,并优先渲染,一般用于pc网页。
*/
</script>
<!-- 双飞翼布局 margin负值实现 因为html结构是父盒子包裹中间区域的元素,另外两个左右区域元素在父元素外面 -->
<div id="container" class="clearfix">
<div class="main"></div>
</div>
<div class="left">left</div>
<div class="right">right</div>
</body>
</html>
现在常用弹性盒子去实现三栏布局,代码简单,效果个人感觉也比圣杯和双飞翼布局更好。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>弹性盒子(经典三栏布局)</title>
<style>
.container {
display: flex;
width: 100%;
height: 500px;
}
.main {
flex: 1;
background-color: yellow;
}
.left {
width: 200px;
height: 100%;
background-color: red;
}
.right {
width: 200px;
height: 100%;
background-color: blue;
}
</style>
</head>
<body>
<div class="container">
<div class="left">left</div>
<div class="main">main</div>
<div class="right">right</div>
</div>
</body>
</html>
1.9 水平垂直居中的实现
这里主要实现水平垂直居中通过 常用的弹性盒子实现 和 以前常使用的绝对定位与位移实现。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>水平垂直居中</title>
<style>
/* 弹性盒子实现 (常用简单) */
.container1 {
width: 500px;
height: 500px;
background-color: aqua;
display: flex;
/* 水平居中 */
justify-content: center;
/* 垂直居中 */
align-items: center;
}
.box1 {
width: 100px;
height: 100px;
background-color: red;
}
/* 绝对定位+位移实现 (以前常用) */
.container2 {
width: 500px;
height: 500px;
background-color: aqua;
position: relative;
}
.box2 {
width: 100px;
height: 100px;
background-color: red;
/* 绝对定位到中间 以盒子左上角为准 */
position: absolute;
top: 50%;
left: 50%;
/* 位移自身宽高的-50% */
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<h3>弹性盒子实现</h3>
<div class="container1">
<div class="box1"></div>
</div>
<h3></h3>
<div class="container2">
<div class="box2"></div>
</div>
</body>
</html>
1.10 line-height如何继承
如果父盒子使用line-height值为数值(20px)和比例(0.5), 那么子盒子直接继承 对应值。
如果父盒子使用line-height值为百分比(30%), 那么子盒子继承 父盒子font-size值 * line-height值(30%) 得到的值。