好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

CSS如何进行性能优化?优化小技巧分享

CSS如何进行性能优化?下面本篇 文章 给大家介绍一些CSS性能优化的小技巧, 希望对大家有所帮助 !

随着 互联网 发展 至今,对于网站来说,性能显的越来越 重要 了,CSS作为页面渲染和内容展现的重要环节,影响着用户对整个网站的第一体验。所以,我们需要重视与CSS相关的性能优化。【推荐学习:css视频教程】

项目开发 初期 我们可能因为各种 原因 (很大一部分原因是因为项目工期,产品往往把项目上线时间卡的死死的,根本不听你说的什么性能优化),怎么写的舒服就怎么来,对于性能优化我们常常在项目完成时才去考虑,经常被推迟到项目的末期,甚至到暴露出严重的性能问题时才进行性能优化。

为了更多地避免这一情况,首先要重视起性能优化相关的工作,将其贯穿到整个 产品设计 与开发中。其次,就是 了解 性能相关的内容,在项目开发 过程中 ,自然而然地进行性能优化。

css渲染规则

想要优化CSS的性能,我们首先需要了解CSS的渲染规则, CSS选择器是从右向左进行匹配的

来看个例子:

.nav h3 a{font- Size:  14px;}复制代码

渲染过程大概是:首先找到所有的 a ,沿着 a 的父元素查找 h3 ,然后再沿着 h3 ,查找 .nav 。中途 找到了 符合匹配规则的节点就加入结果集。如果找到根元素 ht ML 都没有匹配,则不再遍历这条路径,从下一个 a 开始 重复这个查找匹配(只要页面上有多个最右节点为 a )。

Tips:为什么CSS选择器是从右向左匹配的?

CSS中更多的选择器是不会匹配的,所以在考虑性能问题时,需要考虑的是如 何在 选择器不匹配时 提升 效率。从右向左匹配就是为了达成这一目的的,通过这一策略能够使得CSS选择器在不匹配的时候效率更高。这样想来,在匹配时多耗费一些性能也能够想的通了。

内联首屏关键CSS(Cr IT ical CSS)

性能优化中有一个重要的 指标 —— 首次有效 绘制 ( First Meaningful P ai nt,简称FMP)即指页面的首要内容( Primary content)出现在屏幕上的时间。这一指标影响用户看到页面前所需等待的时间,而 内联首屏关键CSS(即Critical CSS,可以称之为首屏关键CSS) 能减少这一时间。

很多人都喜欢通过 link 标签引用外部 CSS文件 。但需要 知道 的是, 将CSS直接内联到HTML文档中能使CSS更快速地下载 。而使用外部CSS文件时,需要在HTML文档下载完成后才知道所要引用的CSS文件,然后才下载它们。所以说, 内联CSS能够使浏览器开始页面渲染的时间提前 ,因为在HTML下载完成之后就能渲染了。

但是我们不 应该 将所有的CSS都内联在HTML文档中,因为[初始拥塞窗口]存在限制 (TCP相关概念,通常是 14.6kB,压缩后大小) ,如果内联CSS后的文件超出了这一限制,系统就需要在 服务器 和浏览器之间进行更多次的往返,这样并不能提前页面渲染时间。因此,我们应当 只将渲染首屏内容所需的关键CSS内联到HTML中 。

⚠️还有 一点 需要注意的是内联CSS没有缓存,每次都会随HTML的加载而重新下载,但我们将内联首屏关键CSS控制在 14.6kB 以内,它对性能优化还是起到正向作用的。(凡事有利也有弊)

异步加载 非首屏CSS

我们需要知道两点内容:(具体可以看我之前的文章:这些浏览器面试题,看看你能回答几个?)

CSS 不会阻塞 DOM 的解析,但会阻塞 DOM 的渲染 CSS 会阻塞 JS 执行,但不会阻塞 JS 文件的下载

由于CSS会阻塞DOM的渲染,所以我们将首屏关键CSS内联后,剩余的非首屏CSS内容可以使用外部CSS,并且异步加载, 防 止非首屏CSS内容阻塞页面的渲染。

CSS异步加载方式

第一种方法是动态创建

// 创建link标签
const myCSS = document.createElement( "link" );
myCSS.rel = "stylesheet";
myCSS. hr ef = " ;m ystyles.css";
// 插入到header的最后位置
document.head.insertBefore( myCSS, document.head.childNodes[ document.head.childNodes.length - 1 ].nextSibling );

第二种方法是将link元素的 media 属性设置为用户浏览器不匹配的媒体类型(或 媒体查询 )

对浏览器来说,如果样式表不适用于当前媒体类型,其优先级会被放低,会在不阻塞页面渲染的情况下再进行下载。在首屏文件加载完成之后,将 media 的值设为 screen 或 all ,从而让浏览器开始解析CSS。

<link rel="stylesheet" href="mystyles.css" media="noexist" onload="this.media=& # 39;all'">

第三种方法是通过 rel 属性将 link 元素标记为 alternate 可选样式表

<link rel="alternate stylesheet" href="mystyles.css" onload="this.rel='stylesheet'">

第 四种 方法是使用 rel= PR eload 来异步 加载css

<link rel="preload" href="mystyles.css" as="style" onload="this.rel='stylesheet'">

注意, as 是必须的。忽略 as 属性, 或者 错误的 as 属性会使 preload 等同于 XHR 请求,浏览器不知道加载的 是什么 内容,因此此类资 源 加载优先级会非常低。 as 的可选值可以参考上述标准文档。

看起来, rel="preload" 的用法和上面两种没什么区别,都是通过更改某些属性,使得浏览器异步加载CSS文件但不解析,直到加载完成并将修改还原,然后开始解析。

但是它们之间其实有一个很重要的不同点,那就是 使用preload,比使用不匹配的 media 方法能够更早地开始加载CSS 。所以尽管这一标准的支持度还不完善,仍建议优先使用该方法。

CSS文件压缩

这应该是最容易想到的一个方法了,通过压缩CSS文件大小来 提高 页面加载速度。现在的构建工具,如webpack、gulp/grunt、rollup等也都支持CSS压缩功能。压缩后的文件能够明显减小,可以大大降低了浏览器的加载时间。

CSS层级嵌套最好不要超过3层

一般情况下,元素的嵌套层级不能超过3级,过度的嵌套会导致代码变得臃肿,沉余,复杂。导致css文件体积变大,造成性能浪费,影响渲染的速度!而且过于依赖HTML文档结构。这样的css样式,维护起来,极度麻烦,如果以后要修改样式,可能要使用 !important 覆盖。尽量 保持 简单 ,不要使用嵌套过多过于复杂的选择器。

删除无用CSS代码

一般情况下,会存在这两种无用的CSS代码:一种是不同元素或者其他情况下的重复代码,一种是整个页面内没有 生效 的CSS代码。

对于前者,在编写的代码时候,我们应该尽可能地提取公共类,减少重复。对于后者,在不同 开发者 进行代码维护的过程中,总会产生不再使用的CSS的代码,当然一个人编写时也有可能出现这一问题。而这些无用的CSS代码不仅会增加浏览器的下载量,还会增加浏览器的解析时间,这对性能来说是很大的消耗。所以我们需要找到并去除这些无用代码。

那么我们如何知道 哪些 CSS代码是无用代码呢?

谷歌 的Ch rom e浏览器就有这种开箱即用的功能。只需转到查看>开发人员>开发人员工具,并在最近的版本中打开Sources选项卡,然后打开命令菜单。然后,点击Coverage,在Coverage analysis窗口中高亮显示当前页面上未使用的代码。

慎用 *通配符

我们有时候可能会写下面这种代码来消除一些标签的默认样式或 统一 浏览器对标签渲染的差异化:

*{
  m arg in:0;
  padding:0;
}

这样虽然代码量少,但它的性能可不是最佳的,我们最好还是写对应的标签选择器:

body,dl,dd, h1 ,h2,h3,h4,h5,h6,p,form,ol,ul{
  mar gin :0;
  padding:0;
}

开发时尽量避免使用通配符选择器

小图片处理方式

一般来讲一个网站上肯定会有很多个小图标,对于这些小图标,目前的主流的解决 方案 有三个, css sprite (雪碧图) , 字体图标 , 把图片转成base64 。

cssSprite: 把所有icon图片合成一张 png图片 ,使用时对节点设置 宽 高,加上bacgroud-position进行背景定位。以背景图方式显展示需要的icon,如果一个网站有20图标,那么就要请求20次,使用 cssSprite ,只需要请求一次,大大的减少了http请求。缺点就是管理不灵活,如果需要新增一个图标,都需要改合并图片的源文件,图标定位也要规范,不然容易干扰图片之间的定位。 字体图标: 简单粗暴的理解就是把所有的图标当成一个字体处理!这样 不用 去请求图片。一般是使用class来定义图标,要替换图标时,只需更换样式名,管理方便,语意 明确 ,灵活放大缩小,并且不会造成失真。但是只支持单色的图片。 base64: 另一种方案就是把小的icon图片转成base64编码,这样可以不用去请求图片,把base64编码直接整合到js或者css里面,可以防止因为一些相对路径,或者图片被不小删除了等问题导致图片404错误。但是找个方式会生成一大串的base64编码。一般来说,8K以下的图片才转换成base64编码。如果把一张50K的图片转成base64编码,那么会生成超过6500 0个 字符的base64编码,字符的大小就已经是将近70K了!建议就是: 8K以下的图片才转换成base64编码。

避免使用@import

不建议使用 @import 主要有以下两点原因:

使用 @import 引入CSS会影响浏览器的并行下载。使用 @import 引用的CSS文件只有在引用它的那个css文件被下载、解析之后,浏览器才会知道还有另外一个css需要下载,这时才去下载,然后下载后开始解析、构建render tree等一 系列 操作。这就导致浏览器无法并行下载所需的样式文件。

多个 @impor t会导致下载顺序紊乱。在IE中, @import 会引发资源文件的下载顺序被打乱,即 排列在@import后面的js文件先于@import下载,并且打乱甚至破坏@import自身的并行下载 。

不要在ID选择器前面进行嵌套其它选择器

在ID选择器前面嵌套其它选择器纯粹是多余的

ID选择器本来就是唯一的而且人家权值那么大,前面嵌套( .content #text )完全是浪费性能。 除了嵌套,在ID选择器前面也不需要加标签或者其它选择器。比如 div#text 或者 .box#text 。这两种方式完全是多余的,理由就是ID在页面就是唯一的。前面加任何东西都是多余的!

删除不必要的单位和零

CSS 支持多种单位和数字格式,可以删除尾随和跟随的零, 零始终是零,添加维度不会为包含的信息附带任何 价值 。

.box {
  padding: .2px;
  margin: 20px;
  avalue: 0;
}

优化回流与重绘

在网站的使用过程中,某些操作会导致样式的 改变 ,这时浏览器需要检测这些改变并重新渲染,其中有些操作所耗费的性能更多。我们都知道,当FPS为60时,用户使用网站时才会感到流畅。这也就是说,我们需要在16.67ms内完成每次渲染相关的所有操作,所以我们要尽量减少耗费更多的操作。

减少回流与重绘

合并对 DOM 样式的修改,采用 css class 来修改

const el = document.querySelector('.box')
el.style.margin = '5px'
el.style.borderRadius = '12px'
el.style.boxShadow = '1px 3px 4px #ccc'

建议使用css class

.update{
  margin: 5px;
  border-dadius: 12px;
  box -s hadow: 1px 3px 4px #ccc
}
const el = document.querySelector('.box')
el.classList.add('update')

如果需要对DOM进行多次访问,尽量使用局部变量缓存该DOM

避免使用table布局,可能很⼩的⼀个⼩改动会造成整个table的重新布局

CSS选择符从右往左匹配查找,避免节点层级过多

DOM离线处理,减少回流重绘次数

离线的DOM不属于当前DOM树中的任何一部分,这也就意味着我们对离线DOM处理就不会引起页面的回流与重绘。

使用 dis play : none ,上面我们说到了 ( display: none ) 将元素从渲染树中完全移除,元素既不可见,也不是布局的组成部分,之后在该DOM上的操作不会触发回流与重绘,操作完之后再将 display 属性 改为 显示,只会触发这一次回流与重绘。

提醒⏰: visibility : hidden 的元素只对重绘有影响, 不影响 重排 。

通过 documentFragment 创建一个 dom 文档片段,在它上面批量操作 dom ,操作完成之后,再添加到文档中,这样只会触发一次重排。
const el = document.querySelector('.box')
const fruits = ['front', 'nanjiu', 'study', 'code'];
const fragment = document.createDocumentFragment();
fruits.for each (item => {
  const li = document.createElement('li');
  li.innerHTML = item;
  fragment.ap PE ndChild(li);
});
el.appendChild(fragment);
克隆节点,修改完再替换原始节点
const el = document.querySelector('.box')
const fruits = ['front', 'nanjiu', 'study', 'code'];
const cloneEl = el.cloneNode(true)
fruits.forEach(item => {
  const li = document.createElement('li');
  li.innerHTML = item;
  cloneEl.appendChild(li);
});
el.parentElement.replaceChild(cloneEl,el)

DOM脱离普通文档流

使用 absoult 或 fixed 让元素脱离普通文档流,使用绝对定位会使的该元素单独成为渲染树中 body 的一个子元素,重排开销比较小,不会对其它节点造成太多影响。

CSS3 硬件 加速(GPU加速)

使用css3硬件加速,可以让 transform、opacity、 filters 这些动画不会引起回流重绘 。但是对于动画的其它属性,比如 background-color 这些,还是会引起回流重绘的, 不过 它还是可以提升这些动画的性能。

常见的触发硬件加速的css属性:

transform opacity filters Will-change

将节点设置为 图层

图层能够阻⽌该节点的渲染⾏为影响别的节点。⽐如对于 video标签 来说,浏览器会⾃动将该节点变为图层。

具体回流与重绘知识点可以看我这篇文章:https://juejin.cn/post/7064077572132323365

(学习视频分享:web前端)

以上就是CSS如何进行性能优化?优化小技巧分享的详细内容,更多请关注其它相关文章!

总结

以上是 为你收集整理的 CSS如何进行性能优化?优化小技巧分享 全部内容,希望文章能够帮你解决 CSS如何进行性能优化?优化小技巧分享 所遇到的问题。

如果觉得 网站内容还不错, 推荐好友。

查看更多关于CSS如何进行性能优化?优化小技巧分享的详细内容...

  阅读:24次