前端面试HTML和CSS总结,这一篇就够了!

  • 前端面试HTML和CSS总结,这一篇就够了!已关闭评论
  • 154 次浏览
  • A+
所属分类:Web前端
摘要

ps:这俩面试答不上来的,基本就可以回去了,以下是HTML题,一般来说这地方不会出太多题,面试官也不愿意花太多时间在这上面。


一,面试基础 HTML和CSS

ps:这俩面试答不上来的,基本就可以回去了,以下是HTML题,一般来说这地方不会出太多题,面试官也不愿意花太多时间在这上面。

1,HTML语义化,如何理解语义化?

让人更容易懂(增加代码的可读性)

让搜索引擎更容易懂,有利于爬虫抓取

在没有css的情况下,页面也能更好的展现出其内容结构,代码·结构

2,script 标签中 defer 和 async 的区别?

script:会阻碍HTML解析,只有下载好并执行完脚本才会继续解析HTML

async:解析HTML的过程中会异步下载脚本,下载成功后立即执行,可能会阻断HTML的解析

defer:完全不会阻断HTML解析,解析完成之后在按顺序执行脚本

图解 script 标签中的 async 和 defer 属性

3,从浏览器地址栏输入 url 到请求返回发生了什么

3.1,输入url之后,会解析出主机,端口,路径,协议等信息,构造一个HTTP请求

3.2,DNS域名解析

3.3,TCP链接,http请求

3.4,服务器处理请求并返回HTTP报文

3.5,浏览器渲染(HTML解析,css解析,js解析,render树)

推文:从输入 URL 开始建立前端知识体系

推文:从 URL 输入到页面展现到底发生什么

推文:字节面试被虐后,是时候搞懂 DNS 了

从上到下依次阅读

4,HTTP和HTTPS的区别

http:

      • 不安全
      • 协议对客户端没有状态存储【没有状态】
      • 每次请求需要TCP三次握手四次挥手,和服务器重新建立连接【没有连接】
      • 基本的特性,由客户端发起请求,服务端响应
      • 简单快速、灵活
      • 使用明文、请求和响应不进行确认

https:

      • 安全
      • HTTP安全版本,通过SSL或TLS提供加密处理数据、验证对方身份以及数据完整性保护
      • 采用混合加密技术,传输过程无法直接查看明文内容【传输加密】
      • 通过证书认证客户端访问的是自己的服务器【身份认证】
      • 传输过程防止被篡改【数据完整】

ps:以下是css的面试题,打不出来的话可能会有非常不好的印象

5,css盒子模型的介绍

css3中盒子模型有两种,一种是W3C标准盒子模型,一种是IE盒子模型

两种盒子模型都是由content,margin,padding,border构成,其大小都是由content,padding,border决定的,但是盒子内容却有所不同:

      • 标准盒模型:只包含 content 。
      • IE(替代)盒模型:content + padding + border 。

前端面试HTML和CSS总结,这一篇就够了!

可以通过 box-sizing 来改变元素的盒模型:

      • box-sizing: content-box :标准盒模型(默认值)。
      • box-sizing: border-box :IE(替代)盒模型。

6,css选择器

选择器 权重 使用示例
!important 1111 * {color: '#00f' !important}
行内 1000 <span style={color:'#00f'} />
id 0100 #id{color:'#00f}
class 0010 .calssName{color:'#00f}
标签 0001 div{color:'#00f}
子选择 0001 div > span{color:'#00f}
伪类 0001 a:hover {color:'#00f}>

优先级的计算规则:

相信每位写过CSS的朋友都知道,CSS选择器的优先级关系是:  内联 > ID选择器 > 类选择器 > 标签选择器

但是,浏览器具体的优先级算法是怎样的?可能还有些人不知道 。《CSS REFACTORING》 中提到了算法的过程 

A specificity is determined by plugging numbers into (a, b, c, d):  If the styles are applied via the style attribute, a=1; otherwise, a=0. b is equal to the number of ID selectors present. c is equal to the number of class selectors, attribute selectors, and pseudoclasses present. d is equal to the number of type selectors and pseudoelements present. 

  简单来说就是通过,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) 出现的总次数。

而比较规则是: 从左往右依次进行比较 ,较大者胜出,如果相等,则继续往右移动一位进行比较 。如果4位全部相等,则后面的会覆盖前面的

举个栗子:

<div class="nav-list" id="nav-list">     <div class="item">nav1</div>     <div class="item">nav2</div> </div>  #nav-list .item {     color: #f00; }  .nav-list .item {     color: #0f0; }

上边代码,算出 #nav-list .item 的优先级是(0,1,1,0) 算出 .nav-list .item  的优先级是(0,0,2,0)

首先比较第一位都是0,相等,往右边找第二位,#nav-list .item的优先级第二位是1,.nav-list .item 优先级的第二位是0,所以#nav-list .item的优先级大于.nav-list .item 

推荐:深入理解 CSS 选择器优先级

7,重排(reflow)和重绘(repaint)的区别

两种概念:

      • 重排:无论通过什么方式影响了元素的几何信息(元素在视口内的位置和尺寸大小),浏览器需要重新计算元素在视口内的几何属性,这个过程叫做重排。
      • 重绘::通过构造渲染树和重排(回流)阶段,我们知道了哪些节点是可见的,以及可见节点的样式和具体的几何信息(元素在视口内的位置和尺寸大小),接下来就可以将渲染树的每个节点都转换为屏幕上的实际像素,这个阶段就叫做重绘。

 如何减少重排和重绘

最小化重绘和重排,比如样式集中改变,使用添加新样式类名 .class 或 cssText

批量操作 DOM,比如读取某元素 offsetWidth 属性存到一个临时变量,再去使用,而不是频繁使用这个计算属性;又比如利用 document.createDocumentFragment() 来添加要被添加的节点,处理完之后再插入到实际 DOM 中

使用 **absolute** 或 **fixed** 使元素脱离文档流,这在制作复杂的动画时对性能的影响比较明显

开启 GPU 加速,利用 css 属性 transformwill-change 等,比如改变元素位置,我们使用 translate 会比使用绝对定位改变其 lefttop 等来的高效,因为它不会触发重排或重绘,transform 使浏览器为元素创建⼀个 GPU 图层,这使得动画元素在一个独立的层中进行渲染。当元素的内容没有发生改变,就没有必要进行重绘作者:vortesnail

浏览器渲染的过程

  1. 解析HTML生成DOM树,解析CSS生成CSSOM树
  2. 将DOM树和CSSOM树结合,生成渲染树(Render Tree)
  3. Layout(回流):根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小)
  4. Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
  5. Display:将像素发送给GPU,展示在页面上。

 前端面试HTML和CSS总结,这一篇就够了!

前端面试HTML和CSS总结,这一篇就够了!

为了构建渲染树,浏览器主要完成了以下工作:

  1. 从DOM树的根部开始遍历出每个可见的节点 (不可见的节点有:script、meta、link等。还有一些通过css进行隐藏的节点。比如display:none)
  2. 对每个可见的节点,找到CSSOM树上对应的规则,并应用他们
  3. 根据每个可见节点以及其对应的样式,组合生成渲染树

注意:渲染树只包含可见的节点

注意,利用visibility和opacity隐藏的节点,还是会显示在渲染树上的。只有display:none的节点才不会显示在渲染树上

从上边的例子我们可以看到span标签的样式有一个display:none,它最终并没有在渲染树上

回流(Layout)

我们通过构造渲染树,将可见DOM节点以及它对应的样式结合起来,可是我们还需要计算它们在设备视口(viewport)内的确切位置和大小,这个计算的阶段就是回流

为了弄清每个对象在网站上的确切大小和位置,浏览器从渲染树的根节点开始遍历,举个栗子:

<!DOCTYPE html> <html>   <head>     <meta name="viewport" content="width=device-width,initial-scale=1">     <title>Critial Path: Hello world!</title>   </head>   <body>     <div style="width: 50%">       <div style="width: 50%">Hello world!</div>     </div>   </body> </html>

我们可以看到,第一个div将节点的显示尺寸设置为视口宽度的50%,第二个div将其尺寸设置为父节点的50%

而在回流这个阶段,我们就需要根据视口具体的宽度,将其转为实际的像素值

前端面试HTML和CSS总结,这一篇就够了!

重绘(Painting)

最终,我们通过构造渲染树和回流阶段,知道了那些元素是可见的,以及可见节点的样式和具体的几何图像信息(也就是在页面上的位置,大小)那么我们就可以将渲染树的每个节点都转换为屏幕上的实际像素,这个阶段就叫做重绘节点

何时会发生回流重绘?

既然前边我们都知道了,回流这一阶段主要是计算节点的位置和几何信息,那么当页面布局和几何信息发生变化的时候,就需要回流。举几个栗子:

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

注意:回流一定会触发重绘,而重绘不一定会回流

根据改变的范围和程度,渲染树中或大或小的部分需要重新计算,有些改变会触发整个页面的重排,比如,滚动条出现的时候或者修改了根节点

推荐腾讯 IVWEB 团队的这篇文章:你真的了解回流和重绘吗

8,对BFC的理解

全程 block format contex 块级格式上下文,就是一块独立渲染区域,不影响文档流

创建 BFC 的方式:

      • 绝对定位元素(position 为 absolute 或 fixed )。
      • 行内块元素,即 display 为 inline-block 。
      • overflow 的值不为 visible 。

推荐文章:可能是最好的 BFC 解析了...

9,实现两栏布局(左侧固定,右侧自适应)

DOM结构:

<div class="outer">   <div class="left">左侧</div>   <div class="right">右侧</div> </div>

方法一:

利用浮动,左边元素宽度固定,右边元素的margin-left固定,注意:右边元素的width是auto,跟随父级自动撑满

.outer {   height: 100px; } .left {   float: left;   width: 200px;   height: 100%;   background: lightcoral; } .right {   margin-left: 200px;   height: 100%;   background: lightseagreen; }

方法二:

同样利用浮动,将左边元素宽度固定,然后給右边元素加上overflow:hidden,这样就触发了 BFC ,BFC的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠

.outer {   height: 100px; } .left {   float: left;   width: 200px;   height: 100%;   background: lightcoral; } .right {   overflow: hidden;   height: 100%;   background: lightseagreen; }

方法三:

利用 flex布局,左边元素固定宽度,右边的元素设置  flex: 1

.outer {   display: flex;   height: 100px; } .left {   width: 200px;   height: 100%;   background: lightcoral; } .right {   flex: 1;   height: 100%;   background: lightseagreen; }

方法四:

利用定位,給父级元素相对定位,給左边元素绝对定位,固定左边元素的宽度,右边元素margin-left 留出位置

.outer {   position: relative;   height: 100px; } .left {   position: absolute;   width: 200px;   height: 100%;   background: lightcoral; } .right {   margin-left: 200px;   height: 100%;   background: lightseagreen; }

方法五:

也是定位,給右边元素绝对定位,給父级相对定位,然后固定左边元素的宽度,給右边元素设置 left 留出位置,剩余的全为0

.outer { position: relative; height: 100px; } .left { width: 200px; height: 100%; background: lightcoral; } .right { position: absolute; left: 200px; top: 0; right: 0; bottom: 0; height: 100%; background: lightseagreen; }

10,实现圣杯布局和双飞翼布局(经典的三栏布局)

询问圣杯布局和双飞翼布局的目的:

  • 三栏布局,中间的内容一定要优先渲染(内容最重要)
  • 两边固定,中间的随着页面自适应
  • 用于pc端页面

技术总结:

  • 使用 float 布局
  • 两侧使用 margin 负值,以便和中间内容横向重叠
  • 防止中间内容被两侧覆盖,圣杯布局用 padding ,双飞翼布局用 margin

圣杯布局:

<div id="container" class="clearfix">   <p class="center">我是中间</p>   <p class="left">我是左边</p>   <p class="right">我是右边</p> </div>

css样式:

#container {   padding-left: 200px;   padding-right: 150px;   overflow: auto; } #container p {   float: left; } .center {   width: 100%;   background-color: lightcoral; } .left {   width: 200px;   position: relative;   left: -200px;   margin-left: -100%;   background-color: lightcyan; } .right {   width: 150px;   margin-right: -150px;   background-color: lightgreen; } .clearfix:after {   content: "";   display: table;   clear: both; }

双飞翼布局:

<div id="main" class="float">   <div id="main-wrap">main</div> </div> <div id="left" class="float">left</div> <div id="right" class="float">right</div>

css样式:

.float {   float: left; } #main {   width: 100%;   height: 200px;   background-color: lightpink; } #main-wrap {   margin: 0 190px 0 190px; } #left {   width: 190px;   height: 200px;   background-color: lightsalmon;   margin-left: -100%; } #right {   width: 190px;   height: 200px;   background-color: lightskyblue;   margin-left: -190px; }

11,水平垂直居中

方法一:flex 布局

.box{   display: flex;   justify-content: center;   align-items: center; }

方法二:利用绝对定位,left:50% top:50% 然后再通过  margin-left  和 margin-top 设置负值实现

.father {   position: relative; } .son {   position: absolute;   left: 50%;   top: 50%;   width: 200px;   height: 200px;   margin-left: -100px;   margin-top: -100px; }

方法三:和上边的方法差不多,但用了css3新增的属性 translate 来实现

.father {   position: relative; } .son {   position: absolute;   left: 50%;   top: 50%;   transform: translate(-50%, -50%); }

方法四:利用绝对定位,子元素所有方向都为 0 ,将 margin  设置为 auto ,由于宽高固定,对应方向实现平分,注意:该方法必须盒子有宽高

.father {   position: relative; } .son {   position: absolute;   top: 0;   left: 0;   right: 0;   bottom: 0px;   margin: auto;   height: 100px;   width: 100px; }

关于div居中的方法还有很多这里推荐一篇:面试官:你能实现多少种水平垂直居中的布局(定宽高和不定宽高)

12,flex布局

Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性,任何一个容器都可以指定为 Flex 布局

推荐阅读:Flex 布局教程 

13,line-height 如何继承?

      • 父元素的 line-height 写了具体数值,比如 30px,则子元素 line-height 继承该值
      • 父元素的 line-height 写了比例,比如 1.5 或 2,则子元素 line-height 也是继承该比例
      • 父元素的 line-height 写了百分比,比如 200%,则子元素 line-height 继承的是父元素 font-size * 200% 计算出来的值