0


2024前端高频面试题之HTML&CSS篇

『前言』: 近期刷面试题时候,总觉得应该梳理出一份清晰且相对全面的前端面试题供自己复习和巩固,其特点是每道题的答案我都会查阅百度百科、官方、查阅多篇博客加上自己的见解进行总结归纳,所以如果有不对的地方,希望可以提出来我会及时改正。

内容共分为:html、css、js、ES6、ts、vue、小程序、git、网络请求相关,本篇内容是 HTML&CSS

文章目录

1,面试题之HTML篇

1,!DOCTYPE (文档类型) 的作用

DOCTYPE 的全称是 Document Type,对应中文:文档类型

<!DOCTYPE>

必须声明在 html 文档的第一行

它的目的是告诉浏览器(解析器)以什么样(html 或 xhtml)的文档类型定义来解析文档

浏览器渲染页面有两种模式:标准模式、混杂模式。可以通过

document.compatMode

获得

  • 标准模式(CSS1Compat):也是默认模式,浏览器使用W3C的标准解析渲染页面,标准模式中,浏览器以其支持的最高标准呈现页面
  • 混杂模式(BackCompat):也是怪异模式,浏览器使用自己的怪异模式解析渲染页面,怪异模式中,浏览器以一种向后兼容的宽松模式来呈现页面
2,HTML meta viewport属性

meta 是元数据元素,用来表示那些其他的不能由 html 元相关元素表示的元数据信息。比如:

link

script

title

标签。
MDN:元数据:简单来说就是描述数据的数据。例如:一个html文件是一种数据,但html文件也能在head元素中包含描述该文档的元数据,比如该文件的作者和概要。

HTML meta viewport 属性是用于控制网页在移动设备上的显示方式的,它可以通过设置不同的值来调整网页的缩放比例、布局和视口大小,以适应不同设备的屏幕尺寸和分辨率

常见的 meta viewport 属性值包括:

1,width: 设置视口的宽度,可以使用具体的像素值比如width=600,也可以使用特定的关键字比如width=device-width表示视口宽度等于设备屏幕的宽度
2,initial-scale: 设置初始缩放比例,可以使用具体的数字值比如initial-scale=2.0,或者使用特性的关键值比如initial-scale=1.0表示不进行缩放
3,minimum-scale和maximum-scale:设置允许用户进行缩放的最小和最大比例
4,user-scalable:设置用户是否可以手动缩放网,可以设置为yes或no,通过设置不同的meta viewport属性值,开发者可以实现响应式设计,使网页在不同设备上呈现出最佳的显示效果
3,对 HTML 语义化的理解?语义元素有哪些?语义化的优点

语义 = 意义, 语义元素 = 有意义的元素

  • 根据内容来选择合适的标签
  • 语义元素:1.<article>内容区域</article>2.<section>区块</section>3.<main>主要区域</main>4.<aside>侧边栏</aside>5.<dialog>定义对话框</dialog>6.<header>头部</header>7.<nav>导航</nav>8.<footer>页脚</footer>
  • 语义化的优点- 代码结构清晰:没有css的情况下,也能呈现出很好的内容结构- 增加可读,开发者能清晰的看出网页的结构,便于团队的开发和维护- 有利于SEO:方便浏览器爬虫更好的识别内容
4,HTML 中 title 、alt 属性的区别
  • alt属性 用在img标签,当图片不显示的时候会出现 alt属性里面的内容,当图片显示的时候不会显示
  • title属性 用在除了htmlheadscriptmetabasebasefont之外的所有标签,title属性是当鼠标放在标签上的时候,会出现一些提示信息
5,src、href 、url 之间的区别
  • 1,含义 - src 引用资源替代当前元素,在imgscriptiframe中使用- href 是超文本引用,指向网络资源所在位置,建立和当前元素或者锚点或者当前文档之间的链接- url 是统一资源定位符,一般来说,对于同一服务器上的文件,应该总是使用相对url用于资源定位
".": 表示目前所在的目录,相对路径
"D:/aaa/": 表示根目录,绝对路径
  • 区别 - a、link 标签使用 href,href 用于在涉及的文档和外部资源之间建立一个关系,href 指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的联系- img、script、iframe 标签使用 src,在可替换的元素上使用 src,在请求 src 资源时会将其指向的资源下载并应用到文档中,比如 JavaScript 脚本,img 图片- url 是统一资源定位符,一般来说,对于同一服务器上的文件,应该总是使用相对url用于资源定位
6,script 标签中的 async、defer的区别

我们知道当浏览器加载 html 的时候一旦遇到了 script 标签,就会停下来先把 script 标签里面的内容给执行掉,如果 script 标签引入的是外部文件,那就必须等待下载和执行完才会继续往下加载,如果外部文件刚好是在一个网络情况较差的服务器上,这样整个网页的加载都会受到很大的影响,这就是同步带来的阻塞弊端。

async 异步 defer 推迟, 他们两个都是异步加载 js,不同的是 async 是 js 一加载完就会马上执行,不管 html 有没有解析完毕,所以它有可能阻塞 html 解析。而 defer 要等到 html 解析完毕之后才执行,所以不会阻塞 html 解析

async 和 defer 属性只有在 script 标签有 src 属性的时候才有效

小问题:

let script = document.createElement('script');
script.src ='xxxxx';// 以上这种形式创建的js是async还是defer呢?创建的script标签会默认设置async为true

7,行内元素、块级元素、空(void)
  • 行内:abspaninputimgselectstrong
  • 块级:pdivh1ulollidldtdd
  • 空:<hr><br><img><input><link><meta>
8,Html5 新特性

html5 不是一种编程语言,而是一种描述性的标记语言,用于描述超文本中的内容和结构

1,语义标签

header头部区域footer底部区域nav导航article文章aside内容之外的内容比如侧边栏section文档中的节

2,表单功能增强

2.1,新增表单类型

邮箱标签:<inputtype="email">
数字标签:<inputtype="number">
滑动条标签:<inputtype="range">
搜索框标签:<inputtype="search">
日期框:<inputtype="date">
星期框:<inputtype="week">
月份框:<inputtype="month">
颜色框:<inputtype="color">
网址框:<inputtype="url"><inputtype="submit"><inputtype="reset">

2.2,新增表单属性

placehoder 输入框默认提示文字
required   要求输入的内容是否可为空
pattern    描述一个正则表达式验证输入的值
min/max    设置元素最小/最大值
step       为输入域规定合法的数字间隔
height/wdith 用于image类型<input>标签图像高度/宽度
autofocus  规定在页面加载时,域自动获得焦点
multiple   规定<input>元素中可选择多个值

2.3,新增表单事件

oninput 每当 input 里的输入框内容发生变化都会触发此事件

oninvalid 当验证不通过时触发此事件

3,新增了音频和视频
4,新增 canvas 绘图

canvas 是在页面中设定一个区域,就可以通过 js 动态的在这个区域中绘制图形

// canvas用法<canvas id="draw" width="300" height="300">当浏览器不支持 canvas 标签的时候会显示这行文字</canvas>let draw = document.querySelector("#draw");
console.log(draw);// 判断是否支持canvas元素if(draw.getContext){let context = draw.getContext("2d");// 通过getContext("2d") 获取 2d 的上下文对象
  context.fillStyle ="#fc5531";
  context.fillRect(10,10,300,300);// 通过fillRect方法绘制的矩形用指定的fillStyle颜色填充,四个参数分别是矩形的x、y坐标、宽、高}
5,新增 svg 绘图

svg 和 canvas 的区别:

  • canvas 可以随时使用 js 绘制 2D 图形
  • svg 是基于 xml 的,意味着可以操作 DOM,渲染速度较慢
  • 在 svg 中每个形状都被当作是一个对象,如果 svg 发生改变,页面会发生重绘
  • canvas 事 1 像素 1 像素的渲染,如果改变某一个位置,整个画布会重绘
// svg用法<svg>// text元素添加文本,x、y定义文本的起点和终点<text x="0" y="10">svg text</text></svg><svg>// cx、cy分别表示新坐标  r是半径 fill是图形的颜色<circle cx="20" xy="50" r="100" fill="#00b96b"/></svg><svg>// x, y 是起始坐标,width 和 height 是图形的宽高<rect x="0" y="0" width="100" height="100" fill="#00b96b"/></svg><svg height="300" width="300"><path d="M 100 100 L 200 200 H 10 V 20" fill="#1cbbb4"/></svg>/**
    d 包含方向命令。这些命令以命令名和一组坐标开始:
    M 表示移动,它接受一组 x,y 坐标
    L 表示直线将绘制到它接受一组 x,y
    H 是一条水平线,它只接受 x 坐标
    V 是一条垂直线,它只接受 y 坐标 Z 表示关闭路径,并将其放回起始位置
/
6,地理定位
  • 使用**getCurrentPosition()**方法来获取用户的位置
  • 可以基于此实现计算位置距离
7,拖放 API
  • 设置元素为可拖放:为了使元素可拖动,把 draggable 属性设置为 true
<p>把图片拖放到矩形中:</p><div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div><br /><img
id="drag1"
src="https://img-home.csdnimg.cn/images/20240218021830.png"
draggable="true"
ondragstart="drag(event)"/>functionallowDrop(ev){
  ev.preventDefault();}functiondrag(ev){
  ev.dataTransfer.setData("Text", ev.target.id);}functiondrop(ev){
  ev.preventDefault();var data = ev.dataTransfer.getData("Text");
  ev.target.appendChild(document.getElementById(data));}/*
    dragstart 事件在用户开始拖动元素或被选择的文本时调用
    dragover 事件在可拖动的元素或者被选择的文本被拖进一个有效的放置目标时(每几百毫秒)触发
    dragenter 事件在可拖动的元素或者被选择的文本进入一个有效的放置目标时触发
    dragleave 事件在拖动的元素或选中的文本离开一个有效的放置目标时被触发
    dragend 事件在拖放操作结束时触发(通过释放鼠标按钮或单击 escape 键)
    drag 事件在用户拖动元素或选择的文本时,每隔几百毫秒就会被触发一次
    drop 事件在元素或文本选择被放置到有效的放置目标上时触发。为确保 drop 事件始终按预期触发,应当在处理 dragover 事件的代码部分始终包含 preventDefault() 调用
*/
8,Web Worker

Web Worker 是在主线程之外运行的

用于解决 JS 单线程中,持续较长的计算,而影响用户的交互

主要用法: 提供主线程和新线程之间数据交换的接口:postMessage、onmessage

// 01.html主线程var workder =newWorker("./01.js");// 创建指向工具js的实例对象
workder.postMessage("我是主线程发送的信息");// 通过postMessage发送主线程的信息
workder.onmessage=function(evt){//接收worker.js传过来的数据函数
  console.log("worker.js发送来的数据=====", evt.data);//输出worker.js发送来的数据};// 01.jsonmessage=function(evt){var data = evt.data;//通过evt.data获得发送来的数据postMessage(`${data}哈哈哈哈`);//将获取到的数据发送会主线程};

9,Web Storage

Web Storage API 提供了浏览器可以存储键/值对的机制,其方式比使用 cookie 更直观

Web Storage 包含如下两种机制:

sessionStorage

为每一个给定的源(origin)维持一个独立的存储区域,该存储区域在页面会话期间可用(即只要浏览器处于打开状态,包括页面重新加载和恢复)。

  • 仅为会话存储数据,这意味着数据将一直存储到浏览器(或选项卡)关闭。
  • 数据永远不会被传输到服务器。
  • 存储限额大于 cookie(最大 5MB)
localStorage

做同样的事情,但即使浏览器关闭并重新打开也仍然存在。

  • 存储的数据没有过期日期,只能通过 JavaScript、清除浏览器缓存或本地存储的数据来清除。
  • 存储限额是两者之间的最大值

这两种机制是通过 Window.sessionStorage 和 Window.localStorage 属性使用,调用其中任一对象会创建 Storage 对象,通过 Storage 对象,可以设置、获取和移除数据项。对于每个源

sessionStorage

localStorage

使用不同的 Storage 对象——独立运行和控制

sessionStoragelocalStorage可使用的 API 相同如下:

保存数据:localStorage.setItem(key,value)
读取数据:localStorage.getItem(key)
删除单个数据:localStorage.removeItem(key)
删除所有数据:localStorage.clear()
得到某个索引的key:localStorage.key(index)
10,WebSocket

WebSocket 是一种在单个 TCP 连接上进行 全双工 通讯的协议(双向通信协议)

什么是全双工:

是通信传输的一个术语,通信允许数据在两个方向上同时传输,在能力上相当于两个单工通信方式的结合。全双工指可以同时进行信号的双向传输(A→B且B→A,)即A→B的同时B→A,是瞬时同步的

与双工通信对应的是单工通信,单工通信就是在只允许A向B发送信息,而乙方不能向甲方传送 。在全双工和单工之间,还有一种通信方式叫“半双工”,是指一个时间段内只允许A向B发送信息,另一个时间段内只允许B向A发送信息,也就是说A和B通过时间段的组合完成双向通信。

列举现实中的例子可以帮助我们更容易理解这些通信方式。
我们日常使用的移动电话、固定电话以及各种远程工作的会议系统都是全双工通信的方式,半双工的通信工具比较典型的是对讲机,某些调度系统也还在使用半双工的方式。单工通信依然非常普遍,例如广播(FM)、电视等

WebSocket 实现客户端和服务端之间的双向通信,允许服务端主动向客户端推送数据,在WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。

WebSocketHTTP的区别:

他们都是基于 TCP 的传输协议,WebSocket 可以双向发送和接受数据,而HTTP是单向的(HTTP 通信只能由客户端发起,不具备服务器主动推送的能力),WebSocket 的使用,需要先进行一次客户端和服务器的握手,两者建立连接后才可以正常双向通信,而HTTP是一个主动的请求对应一个被动的响应

WebSocket 的协议标识符?

如果服务器网址是 HTTP 那么 WebSocket 对应的是 ws

如果服务器网址是 HTTPS 加密的 那么 WebSocket 对应的是 wss

WebSocket 是为了能够实现在 web 应用上与服务器进行双向通信的需求 而产生出来的协议,

相比于轮询 HTTP 请求的方式,WebSocket 节省了服务器资源,有效的提高了效率

WebSocket 常用方法:

  • Socket.send():通过 Socket 向服务器发送信息
  • Socket.close():关闭 Socket 连接

WebSocket 常用属性:

  • Socket.readyState获取当前链接状态****0:正在连接中,1:连接正常可以通信,2:连接关闭中,3:连接已关闭/连接失败
  • Socket.url获取当前连接地址
  • Socket.binaryType获取传输的数据类型

WebSocket 生命周期:

  • Socket.onopen连接建立时触发
  • Socket.onmessage客户端接收服务端数据时触发
  • Socket.onerror通信发生错误时触发
  • Socket.onclose连接关闭时触发
9,浏览器渲染页面的步骤
  • 1,解析html,生成DOM树;解析CSS,生成CSSOM树
  • 2,将DOM树和CSSOM树结合,生成渲染树(Render Tree)
  • 3,Layout(回流):根据生成的渲染树,计算它们在设备视口(viewport)内的确切位置和大小,这个阶段是回流
  • 4,Painting(重绘):根据渲染树以及回流得到的几个信息,得到节点的绝对像素
  • 5,Display:将像素发送给GPU,展示在页面上在这里插入图片描述
10,DOM的重绘(Repaint)和重排(回流)(Reflow)
1,重绘

重绘: 元素样式的改变(但宽高、大小、位置等不变)

  • 比如我只是把当前元素的背景颜色变了
  • Outline、visibility、color、background-color等
2,重排

重排:元素的大小或者位置发生变化(当页面布局和几何信息发生变化的时候),触发了重新布局,导致渲染树重新计算布局和渲染

  • 如添加或者删除可见的DOM元素
  • 元素的位置发生变化
  • 元素的尺寸发生变化
  • 内容发生变化(比如文本变化或者图片被另一个不同尺寸的图片所替代)
  • 页面一开始渲染的时候,这个无法避免,因为回流是根据视口大小来计算元素的位置和大小的,所以浏览器的窗口尺寸变化会引发回流
  • 回流就是结构得重新算这就是回流

注意:重排一定会触发重绘,重绘不一定触发重排

3,避免DOM的回流的方案
1,放弃传统操作DOM的时代,基于vue/react开始数据影响视图模式

Mvvm、mvc、virtual dom、dom diff

2,DOM操作的分离读写(现代的浏览器都有渲染队列的机制)
offsetTop、offsetLeft、offsetWidth、offsetHeight、clientTop、clientLeft、clientWidth、clientHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、getComputedStyle、currentStyle....这些都会刷新渲染队列
<div id="box"></div>
box.style.width ="100px";
box.style.height ="100px";
box.style.background ="red";// => 重绘制
box.style.margin ="20px auto";// => 以上代码会引发几次回流(重排)?// => 1次// => 因为现代版浏览器都有“渲染队列”机制:发现某一行要修改元素的样式,不立即渲染,而是看看下一行,如果下一行也会改变样式,则把修改样式的操作放到“渲染队列中”.....一直到不再是修改样式的操作后,整体渲染一次,引起一次回流

读写分离:

box.style.width ="100px";// => 写
console.log(box.offsetWidth)// => 读
box.style.height ="100px";// => 写
console.log(box.offsetHeight)// => 读
box.style.background ="red";// => 写
box.style.margin ="20px auto";// => 写// => 以上读的时候(console.log(box.offsetWidth)),会引发一次回流,所以以上代码会引发3次回流。所以要读写分离

box.style.width ="100px";// => 写
box.style.height ="100px";// => 写
box.style.background ="red";// => 写
box.style.margin ="20px auto";// => 写
console.log(box.offsetWidth)// => 读
console.log(box.offsetHeight)// => 读// => 把读和写分开来做
3,样式集中改变
.box {width: 100px;height: 100px;
  background-color: aqua;margin: 20px auto;}<div id="boxId"></div>// 方式一:
div.className ='box'// => 方式二:
div.style.cssText ='width: 20px; height: 20px'
4,缓存布局信息(它的原理是读写分离)
div.style.left = div.offsetLeft +1+'px'
div.style.top = div.offsetTop +1+'px'// => 改为var curLeft = div.offsetLeft
var curTop = div.offsetTop
div.style.left = curLeft +1+'px'
div.style.top = curTop +1+'px'
5,元素批量修改

1, 文档碎片:createDocumentFragment

// => 假设我想给box动态加10个 span <div id="box"></div>for(let i =0; i <10; i++){let span = document.createElement("span");
  span.innerHTML = i;
  box.appendChild(span);}// => 以上方法引发10次回流// => 方式1: 使用文档碎片let frg = document.createDocumentFragment();// 文档碎片:存储文档的容器for(let i =0; i <10; i++){let span = document.createElement("span");
  span.innerHTML = i;
  frg.appendChild(span);}
box.appendChild(frg);
frg =null// => 引发一次回流// => 方式2: 使用模版字符串拼接let str =``;for(let i =0; i <10; i++){
  str +=`<span>${i}</span>`;}
box.innerHTML = str;// => 引发一次回流
6,动画效果应用到position属性为absolute或者fixed的元素上,因为它们脱离文档流,不会引发其他元素的回流
7,CSS3硬件加速(GPU加速)

比起考虑如何减少回流重绘,我们更期望的是,根本不要回流重绘:transform/opacity/filters…这些属性会触发硬件加速,不会引发回流和重绘

可能会引发的坑:过多使用会占用大量内存,性能消耗严重,有时候会导致字体模糊等

8,牺牲平滑度换取速度

每次1像素移动一个动画,但是如果此动画使用了100%的CPU,动画就会看上去是跳动的,因为浏览器正在与更新回流做斗争,每次移动3像素可能看起来平滑度低了,但它不会导致CPU在较慢的机器中抖动

9,避免table布局和使用css的javascript表达式

2,面试题之 CSS 篇

1,介绍一下 CSS 的盒子模型

w3c

规范中,盒子模型被定义为一个元素所占用的网页空间。

盒模型由 4 部分组成:margin(外边距)、border(边框)、padding(内边距)、content(内容)

盒子大小的计算模型有两种:标准盒模型、IE 盒模型,通过改变 css 的 box-sizing 属性的值来改变

两种盒模型的区别在于设置 width 和 height 的时候,对应的范围不同。

  • 标准盒模型:box-sizing 的值为 content-box(也是默认值),这种行为模式下,盒子的宽和高只决定元素的 content 内容部分,而 padding 和 border 是在 content 外部另外绘制,也就是说 width = contentdiv{width: 100px;padding: 15px;border: 2px solid #ccc;margin: 30px;box-sizing: content-box;}

  • IE 盒模型:box-sizing 的值为 border-box,这种行为模式下,为盒子设定的宽和高决定了元素的大小,盒子的 padding 和 border 都将在已设定好的宽高内绘制,也就是说 width = content + padding + border

2,CSS3 新特性
  • 1,边框:- 圆角效果 border-radiusborder-radius:10px 20px 30px 40px;/** 4个值分别表示左上角,右上角,右下角,左下角 */- 边框阴影 border-shadowborder-shadow: X轴偏移量 Y轴偏移量 阴影模糊半径 扩散半径 阴影颜色;比如: /** x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影扩散半径 | 阴影颜色 */box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);/** 任意数量的阴影,以逗号分隔 */box-shadow: 3px 3px red, -1em 0 0.4em olive;
  • 2,颜色:- rgbar g b 三个参数取值范围都是:0 ~ 255 或者 0.0%~ 100%,a 为透明度,取值范围为:0 ~ 1background-color:rgba(255,255,255,0.3);- 渐变- linear-gradient() 线性渐变- radial-gradient()径向渐变- repeating-linear-gradient()、repeating-radial-gradient()重复渐变- conic-gradient()锥形渐变
  • 3,文字与字体:- text-overflowtext-overflow 用于提示用户存在隐藏的溢出内容,其形式显示一个省略号或者一个自定义字符串text-overflow:clip(表示剪切) | ellipsis(表示显示省略标记);但是 text-overflow 只是用来说明文字溢出时用什么方式显示,要实现溢出时产生省略号的效果,还须其他条件:定义强制文本在一行显示(white-space:nowrap) 溢出内容为隐藏(overflow:hidden)text-overflow:ellipsis;overflow:hidden;white-space:nowrap;word-wrap 用来设置文本行为,当前行超过指定容器的边界时是否断开转行word-wrap:normal |break-word;- 文字阴影 text-shadowtext-shadow:x-offset y-offset blur color;/** 阴影水平偏移距离 阴影垂直偏移距离 阴影模糊程度 阴影颜色*/
  • 4,css 变形- 旋转 rotate(): 相对原点进行旋转- 缩放 scale(): 根据中心原点对对象进行缩放
  • 5,盒模型 box-sizingbox-sizing: content-box | border-box | inherit /** inherit:使元素继承父元素的盒模型模式 */
  • 6,弹性布局 flexbox 阮一峰 Flex 布局教程Flex 布局将在下面详细介绍 👇
  • 7,动画 animation
3,Flex 弹性布局

常见的考题:

1,flex: 1 表示什么

flex: 1

flex-grow

flex-shrink

flex-basis

的缩写,默认值是

0 1 auto

``flex:1

flex: 1 1 auto`

  1. flex-grow定义项目放大比例,默认为 0,即如果存在剩余空间,也不放大
  2. flex-shrink定义项目的缩小比例,默认为 1,即如果空间不足,该项目将缩小
  3. flex-basis定义在分配多余空间之前,项目占据的主轴空间,浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小

2,看效果写代码或者说出实现思路

<div class="container">
  <div class="item"></div>
  <div class="item"></div>
    <div class="item"></div>
</div>
.container{width: 200px;height: 200px;background-color:rgb(239, 253, 212);display: flex;justify-content: space-between;}.item{width: 60px;height: 60px;background-color:rgb(144, 0, 255);}.container div:nth-of-type(2){align-self: center;}.container div:nth-of-type(3){align-self: flex-end;}

3,看效果说出实现的思路

<div class="container">
  <div class="first">
    <div class="item"></div>
    <div class="item"></div>
  </div>
  <div class="second">
      <div class="item"></div>
  </div>
  <div class="second">
    <div class="item"></div>
    <div class="item"></div>
  </div>
</div>
.container{width: 200px;height: 200px;background-color:rgb(239, 253, 212);display: flex;justify-content: space-between;}.item{width: 60px;height: 60px;background-color:rgb(144, 0, 255);}.first,
.three{display: flex;flex-direction: column;justify-content: space-between;}.second{align-self: center;}

4,看效果说出实现思路

<div class="container">
  <div class="first">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
  <div class="second">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
</div>
.container{width: 200px;height: 200px;background-color:rgb(239, 253, 212);display: flex;justify-content: space-between;}.item{width: 80px;height: 80px;margin-bottom: 3px;background-color:rgb(144, 0, 255);}.first,
.second,
.three{display: flex;flex-direction: column;justify-content: space-between;}

更多案例参考阮一峰大佬的 Flex 教程

下面简单介绍一下 Flex 布局:

任何一个容器都可以指定为 Flex 布局:display: flex; 行内元素也可以使用 Flex 布局:display: inline-flex

采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"

容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做

main start

,结束位置叫做

main end

;交叉轴的开始位置叫做

cross start

,结束位置叫做

cross end

项目默认沿主轴排列。单个项目占据的主轴空间叫做

main size

,占据的交叉轴空间叫做

cross size

Flex 容器有 6 个属性:

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

1,flex-direction:决定主轴的方向(即项目的排列方向)

flex-direction: row | row-reverse | column | column-reverse;
                row(默认值):主轴为水平方向,起点在左端。
                row-reverse:主轴为水平方向,起点在右端。
                column:主轴为垂直方向,起点在上沿。
                column-reverse:主轴为垂直方向,起点在下沿

2,flex-wrap:如果一条轴线排不下,如何换行

flex-wrap: nowrap | wrap | wrap-reverse;
            nowrap(默认):不换行
            wrap:换行,第一行在上方
            wrap-reverse:换行,第一行在下方

3,flex-flow:是

flex-direction

属性和

flex-wrap

属性的简写形式,默认值为

row nowrap
flex-flow: <flex-direction> || <flex-wrap>;

4,justify-content:定义项目在主轴上的对齐方式

justify-content: flex-start | flex-end | center | space-between | space-around;
                flex-start(默认值):左对齐
                flex-end:右对齐
                center: 居中
                space-between:两端对齐,项目之间的间隔都相等。
                space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍

5,align-items:定义项目在垂直的交叉轴上如何对齐

align-items: flex-start | flex-end | center | baseline | stretch;
            flex-start:交叉轴的起点对齐。
            flex-end:交叉轴的终点对齐。
            center:交叉轴的中点对齐。
            baseline: 项目的第一行文字的基线对齐。
            stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度

6,align-content:定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用

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

其他内容就不写了,可以看阮神的 Flex 教程](https://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=tuicool)很详细超赞的文章

4,CSS 选择器和优先级

选择器
选择器权重id 选择器

#id

100类选择器

.classname

10属性选择器

div[class="foo"]

10伪类选择器

div::last-child

10标签选择器

div

1伪元素选择器

div:after

1兄弟选择器

div+span

0子选择器

ui>li

0后代选择器

div span

0通配符选择器0
优先级

!important

内联样式 > ID 选择器 > 类选择器/伪类选择器/属性选择器 > 标签选择器/伪元素选择器 > 关系选择器/通配符选择器

5,伪元素和伪类的区别
  • 伪元素创建了一个新元素,用::表示,比如::before 或者::after(目前一部分浏览器为了达到一个更好的兼容性效果,双冒号可以写成单冒号,但是一些低版本浏览器还是不支持的)
  • 伪类是一个已经存在的元素但是不能被我们看到, 用:表示,比如::hover

常见的伪元素有哪些:

  • ::before、::after 表示元素内容区域的前面、后面
  • ::first-letter 表示第一个字
  • ::first-line 表示第一行
  • ::section 表示选中部分
  • ::placeholder 表示占位文本

常见的伪类:

  • :link 未点击的时候
  • :visited 点击时
  • :hover 悬停时
  • :active 被激活时
  • :focus 聚焦时
  • :not(x) 不是 x
  • :first-child 第一个
  • :last-child 最后一个
  • :nth-child(x) 第 x 个
  • :nth-last-child(x) 倒数第 x 个
  • :checked 选中
  • :disabled 禁用
6,移动端 1px 问题及解决办法
1,认识设备的物理像素(设备像素)、逻辑像素(css 像素)、设备像素比 dpr
  • 物理像素:设备在出厂的时候,不同设备自带的不同像素就是 UI 设计师使用的像素
  • 逻辑像素:也就是我们开发时 css 记录的像素
  • DPR(devicePixelRatio) 设备像素比,它是设备像素和 CSS 像素的比值,可以用 js 中的window.devicePixelRatio来获取:dpr = 物理像素 / CSS 像素

在移动端开发中,UI 设计稿中设置边框为 1 像素,前端在开发过程中设置 border = 1px,测试人员会发现在某些机型上 1px 会比较粗,这就是经典的移动端 1px 像素问题

2,产生 1px 问题的原因

自从 2010 年 iPhone4 推出了 Retina 屏开始,移动设备屏幕的像素密度越来越高,于是便有了 2 倍屏、3 倍屏的概念。简单来说,就是手机屏幕尺寸没有发生变化,但屏幕的分辨率却提高了一倍,即同样大小的屏幕上,像素多了一倍。所以移动端页面的

1px

会变得很粗,呈现出不止

1px

的效果,产生 1px 问题的主要原因就是 dpr。

目前主流的屏幕 dpr=2(iPhone6/7/8),或者 dpr=3(iPhone X),拿 2 倍屏来说,dpr = 物理像素 / css 像素,dpr 为 2,物理像素为 1px,所以可以得出逻辑像素( css 像素)为 0.5px。一般设计稿是按 750 来设计的,它上面的 1px 是以 750 来参照的,而我们写 css 样式是以设备 375 为参照的,所以我们写 0.5px 即可。

3,解决办法
1,设置 viewport 的 scale 值
<meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>let viewport = document.querySelector("meta[name=viewport]");//根据设备像素设置viewportif(window.devicePixelRatio ==1){
  viewport.setAttribute("content","width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no");}if(window.devicePixelRatio ==2){
  viewport.setAttribute("content","width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no");}if(window.devicePixelRatio ==3){
  viewport.setAttribute("content","width=device-width,initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no");}var docEl = document.documentElement;var fontsize =32*(docEl.clientWidth /750)+"px";
docEl.style.fontSize = fontsize;

2,利用伪元素
// 1条border
div{position: relative;&::after{position: absolute;content:"";background-color: red;top: 0;left: 0;width: 100%;height: 1px;transform:scale(1, 0.5);}}// 4条border
div{position: relative;&::after{position: absolute;content:"";top: 0;left: 0;border: 1px solid red;width: 200%;height: 200%;transform-origin: left top;transform:scale(0.5);}}
3,直接写0.5px
div{border-top: 0.5px solid red;}
7,css 常见单位
  • px :物理像素,是相对于显示器屏幕分辨率的
  • emremem是相对于父元素的,rem相对于根元素html
  • vwvh:和浏览器窗口大小有关的单位,他们的参照对象都是浏览器窗口, - vw浏览器窗口宽度的百分比:假设浏览器宽度1000px,则`1vw = 浏览器窗口宽度的 1% = 10px- vh,浏览器窗口高度的百分比:假设浏览器高度1000px,则1vh = 浏览器窗口高度的1% = 10px
  • %:是相对父元素的,当浏览器的宽和高改变时,当前元素也会根据比例发生改变
8,水平垂直居中、两栏布局、三栏布局的实现
1,水平垂直居中
1,利用绝对定位,设置四个方向的值都为 0,并将
margin

设置为

auto

由于宽高固定,因此对应方向实现平分,可以实现水平和垂直方向上的居中

.parent{position: relative;}.child{position: absolute;top: 0;bottom: 0;left: 0;right: 0;margin: auto;}
2,利用绝对定位,再通过
translate

调整

先将元素的左上角通过

top:50%

left:50%

定位到页面的中心,然后再通过

translate

来调整元素的中心点到页面的中心

.child{position: absolute;top: 50%;left: 50%;transform:translate(-50%, -50%);}
3,利用绝对定位,再通过 margin 负值进行调整

先将元素的左上角通过

top:50%

left:50%

定位到页面的中心,然后再通过

margin

负值来调整元素的中心点到页面的中心

.child{position: absolute;top: 50%;left: 50%;margin-top: -40px;/** 自身高度的一半 */margin-left: -40px;/** 自身宽度的一半 */}
4,使用flex布局

通过

align-items:center

justify-content:center

设置容器的垂直和水平方向上为居中对齐,然后它的子元素也可以实现垂直和水平的居中

.parent{display: flex;justify-content: center;align-items: center;}
2,两栏布局

两栏布局非常常见,通常是一个宽度固定和一个宽度自适应的布局排列展示,如下形式展示

1,方法 1:float + margin 实现
<div class="box">
  <div class="left">left</div>
  <div class="right">right</div>
</div>
.left{width: 200px;float: left;}.right{width: auto;margin-left: 200px;}
2,方法 2:左 float,右 overflow:hidden 触发 BFC

利用左 float,右 overflow:hidden 这样右边就会触发 BFC,BFC 的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠

.left{width: 200px;float: left;}.right{overflow: hidden;}
3,方法 3:左绝对定位,右 margin 负值

将父级元素设置为相对定位。左边元素设置为 absolute 定位,并且宽度设置为 200px。将右边元素的 margin-left 的值设置为 200px

.box{position: relative;}.left{width: 200px;position: absolute;}.right{margin-left: 200px;}
4,方法 4:Flex 布局

将左边元素设置为固定宽度 200px,将右边的元素设置为 flex:1

.box{display: flex;}.left{width: 200px;}.right{flex: 1;}
3,三栏布局

三栏布局:两边固定,中间自适应

1,流体布局(float 布局):

利用左右浮动,中间设置左右两个方向的 margin 值,注意 ⚠️:中间一栏必须放到最后

<div class="box">
  <div class="left">left</div>
  <div class="right">right</div>
  <div class="mid">middle</div>  /** 中间一栏必须放到最后 */</div>
.left{width: 200px;float: left;}.right{width: 300px;float: right;}.mid{height: 200px;margin-left: 200px;margin-right: 300px;}
2,BFC 布局:

两栏浮动,中间不做任何属性,这时中间栏默认是撑满全屏的,我们利用 BFC 的规则- BFC 不会和浮动元素重叠,把中间元素改成 BFC,使用 overflow: hidden;或者 display: flex;

<div class="box">
  <div class="left">left</div>
  <div class="right">right</div>
  <div class="mid">middle</div> /** 这种情况,中间一栏也必须放到最后 */</div>
.left{width: 200px;float: left;}.right{width: 300px;float: right;}.mid{height: 200px;/* overflow: hidden; */display: flex;/** overflow: hidden; 或者 display: flex;  */}
3,Flex 布局:

父元素使用 flex 属性,中间使用 flex: 1 占据剩余空间

<div class="box">
  <div class="left">left</div>
  <div class="mid">middle</div>
  <div class="right">right</div>
</div>
.box{display: flex;}.left{width: 200px;}.right{width: 300px;}.mid{height: 200px;flex: 1;}
4,position 定位:

左右绝对定位,中间设置对应方向大小的 margin 值

.box{position: relative;}.left{width: 200px;position: absolute;top: 0;left: 0;}.right{width: 300px;position: absolute;top: 0;right: 0;}.mid{height: 200px;margin-left: 200px;margin-right: 300px;}
5,圣杯布局:

利用浮动、负边距、相对定位实现。三列均设置左浮动,左右定宽,中间宽度 100%,中间一列放在最前面,然后通过负边距进行调整,这时中间栏还是占据 100%宽度,所以我们操作父元素给出和左右两栏相等的内边距,但是我们发现整体盒子被压缩了,所以我们再利用相对定位定到两边即可

<div class="box">
  <div class="mid">middle</div>
  <div class="left">left</div>
  <div class="right">right</div>
</div>
.box{padding-left: 200px;/** 中间的元素宽度占满100%,所以文字被挡住了,我们操作父元素给出和左右两栏相等的内边距*/padding-right: 300px;}.left{width: 200px;float: left;margin-left: -100%;/** 先让三栏位于一行,左栏设置margin-left: -100%,此时左栏位于第一行首部*/position: relative;left: -200px;}.right{width: 300px;float: left;margin-left: -300px;position: relative;right: -300px;}.mid{width: 100%;float: left;}
6,双飞翼布局:

双飞翼布局可以说是圣杯布局的改进版,他们达到的效果相同,都是侧边两栏宽度固定,中间栏宽度自适应。主要的区别在于解决中间部分被挡住的问题时,圣杯是在父元素上设置了左右内边距,再给左右设置相对定位,通过左移和右移即可。而双飞翼是在中间栏再加个 div 来放置内容,再给这个新的 div 设置 margin 值来避开遮挡即可

<div class="box">
  <div class="mid">
      <div class="midContent">middle</div>
  </div>
  <div class="left">left</div>
  <div class="right">right</div>
</div>
.left{width: 200px;height: 200px;background-color:rgb(172, 254, 224);float: left;margin-left: -100%;/** 先让三栏位于一行,左栏设置margin-left: -100%,此时左栏位于第一行首部*/}.mid{float: left;width: 100%;}.midContent{height: 200px;background-color: yellow;margin-left: 200px;margin-right: 300px;}.right{width: 300px;height: 200px;background-color:rgb(228, 135, 249);float: left;margin-left: -300px;}
9,link 和 @import 的区别

两者都是外部引用 css 的方式,区别如下:

  • link 是 xhtml 标签,除了引入 css 外,还可以用来定义 RSS;@import 属于 css 范畴,只能加载 css
  • link 引用 css 的时候,在页面载入时同时加载。 @import 需要页面完全加载完成后加载
  • link 是 xhtml 标签,无兼容问题,@import 是 css2 提出来的,低版本的浏览器不支持
  • link 支持 js 去控制 DOM 去改变样式,@import 不支持
10,display 属性值及其作用

属性值作用none元素不可见,并且会从文档流中移除block块类型,默认宽度为父元素宽度,可设置宽高,换行显示inline行内元素类型, 默认宽度为内容宽度,不可设置宽高,同行显示inline-block默认宽度为内容宽度,可以设置宽高,同行显示table此元素会作为块级表格来显示inherit规定应该从父元素继承 display 属性的值list-item像块类型元素一样显示,并添加样式列表标记
display 的 block、inline 和 inline-block 的区别

(1)block:会独占一行,多个元素会另起一行,可以设置 width、height、margin 和 padding 属性
(2)inline:元素不会独占一行,设置 width、height 属性无效,但可以设置水平方向的 margin 和 padding 属性,不能设置垂直方向的 padding 和 margin
(3)inline-block:将对象设置为 inline 对象,但对象的内容作为 block 对象呈现,之后的内联对象会被排列在同一行内

11,position 常见的属性值
  • static :静态定位,top、bottom、left、right 属性无效,等同于没有定位
  • relative :相对定位,top、bottom、left、right 相对于该对象在标准文档流中的位置进行偏移
  • absolute :绝对定位,相对于 static 定位以外的第一个父元素进行定位
  • fixed :固定定位,相对于浏览器窗口进行定位
  • sticky :粘性定位,相对于用户滚动位置进行定位
12,隐藏元素的方法有哪些
  • Display: none; 渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会影响绑定的监听事件
  • Visibility: hidden; 元素在页面中仍占据位置,但是不会响应绑定的监听事件
  • Opacity: 0; 将元素的透明度设置为 0,元素在页面中仍占据位置,会响应绑定的监听事件
  • Position: absolute; 通过绝对定位将元素移除可视区域内
  • Z-index: 负值;来使其他元素遮盖住该元素
  • Transform: scale(0, 0)将元素缩放为 0 来实现元素的隐藏,元素在页面中仍占据位置,会响应绑定的监听事件

display: none; 和 visibility: hidden 的区别

(1)渲染树中

  • Display: none; 会让元素从渲染树中消失,不占位置
  • Visibility: hidden; 不会让元素从渲染树中消失,占据位置

(2)是否是继承属性

  • Display: none;是非继承属性,子元素会随着父元素消失而消失,通过修改子元素的属性无法使其显示
  • Visibility: hidden 是继承性属性,子元素会随着父元素消失而消失,通过修改子元素的属性可以使其显示
13,CSS 中可继承与不可继承属性
1,可继承
  • font-family、font-weight、font-size
  • line-height、color
  • visibility
2,不可继承
  • width、height
  • margin、padding、border
  • background
  • position、left、right、top、bottom
  • display
14,css 实现三角形
div{width: 0;height: 0;border-top: 50px solid pink;border-left: 50px solid transparent;border-right: 50px solid transparent;}/**使用边框实现*/

15,BFC
1,什么是 BFC?其规则是什么?

BFC 的全称是 Block formatting context 对应中文是:块级格式化上下文,它是一个独立的渲染区域,我们可以把 BFC 理解为一个封闭的容器,内部的元素无论怎么布局都不会影响外部,容器内的样式布局自然也不会受外界的影响。

它内部的规则有:

  • 1,BFC 就是一个块级元素,块级元素会在垂直方向一个接一个排列
  • 2,BFC 就是页面中的一个隔离的独立容器,容器里的标签不会影响到外部标签
  • 3,BFC 区域不会与浮动的容器发生重叠
  • 4,属于同一个 BFC 的两个相邻元素的外边距会发生重叠,垂直方向的距离由两个元素中 margin 的较大值决定
  • 5,计算 BFC 的高度时,浮动元素也会参与计算
2,如何触发 BFC

我们可以通过添加一些 css 属性来触发,常见的有:

  • overflower 除了 visible 以外的值
  • position 的值设置为 absolute 或者 fixed
  • display 的值设置为 inline-block 或者 flex
3,BFC 到底可以解决什么问题呢
  • 1,它可以阻止元素被浮动元素覆盖,比如两栏布局<div class="left">left</div><div class="right">right</div>.left{width: 100px;height: 100px;border: 1px solid aqua;float: left;}.right{background-color:rgb(255, 200, 209);}

由图可以看出,由于左边的 div 浮动后脱离文档流不占空间了,就会导致右边的 div 到了最左边,同时左侧浮动的 div 还会覆盖在上面,这时候我们就可以通过把右侧的 div 设置为一个 BFC,比如可以给它添加 display: flex 来触发,就可以解决右侧被左侧覆盖的问题

.right{width: auto;background-color:rgb(255, 200, 209);display: flex;}

  • 2,解决父元素没有高度,子元素设置为浮动元素时,产生的父元素高度塌陷的问题,比如一个容器内的两个 div 都是浮动元素,此时给父元素设置背景色是没有任何效果的,因为此时父元素的高度为 0<div class="p"> <div>1</div> <div>2</div></div>.p div{width: 100px;height: 100px;border: 1px solid aqua;float: left;}.p{background-color:rgb(157, 255, 0);}

这时候我们就可以添加一个可以触发父元素 BFC 功能的属性,因为 BFC 有个规则是计算 BFC 的高度时,浮动元素也参与计算,所以触发 BFC 后,父元素的高度就会被撑开,也就是会产生清除浮动的效果

.p{background-color:rgb(157, 255, 0);overflow: hidden;}

  • 3,可以解决 margin 边距重叠的问题,比如一个容器里有两个 div,这两个 div 分别设置了自己的 margin,一个是 10px,一个是 20px,正常两个盒子的垂直距离是 30px,不然,我们会发现两个盒子之间的垂直距离是 20px,这就是 margin 塌陷问题
<div>
  <div class="t">1</div>
  <div class="b">2</div>
</div>
.t,
.b{width: 100px;height: 100px;background-color:rgb(245, 108, 73);margin: 10px;}.b{background-color: paleturquoise;margin: 20px;}

这就是 margin 塌陷问题,此时 margin 边距的结果为两个 div 间的较大值,如果我们想让 margin 外边距变为正常的 30,可以触发一个 div 的 BFC,它的内部就会遵循 BFC 规则,这样就可以为元素包裹一个盒子形成一个完全独立的空间,做到里面的元素不受外部元素的影响

<div>
    <div class="t">1</div>
    <div style="overflow: hidden">
        <div class="b">2</div>
    </div>
</div>

标签: 面试 前端 html5

本文转载自: https://blog.csdn.net/m0_37489258/article/details/136558593
版权归原作者 西柚Baby 所有, 如有侵权,请联系我们删除。

“2024前端高频面试题之HTML&CSS篇”的评论:

还没有评论