根据httparchive.org的页面重量报告,CSS在平均70个请求和2MB的网页上占7个HTTP请求和70Kb的代码。这并不是网站性能糟糕的最坏原因(我正看着你呢,JavaScript),但CSS面临着特定的挑战:
- CSS会阻止渲染:每个 <link> and @import halts other downloads while the browser downloads and parses the required CSS file.
- CSS可以请求其他资产:CSS可以引用图像、视频、字体和其他CSS文件,这会导致附加下载的级联。
- CSS代码随时间增长:识别未使用的样式可能很有挑战性,删除错误的样式会导致混乱。开发人员采取简单的方法,向不断增长的样式表添加更多属性。文件越大,下载和处理时间就越长。
- CSS影响渲染:浏览器分三个阶段呈现页面:布局(元素尺寸)、绘画(文本、颜色、边框、阴影等)、和复合(定位)。某些CSS属性会触发所有三个阶段,这可能会降低性能。
下面的30个技巧将帮助您优化CSS,以改善实际和感知的响应时间。
1.使用CSS性能分析工具
衡量是确定业绩机会和评估收益的唯一途径。所有浏览器都提供DevTools面板,通常通过“更多工具”菜单或键盘快捷键Ctrl打开|按下Cmd + Shift +i或F12组合键。
“网络”面板是一个很好的起点,刷新后,它会显示资源下载的瀑布图:
较长的条突出显示加载缓慢或渲染受阻的资源(如上图中的白色块所示)。
该灯塔Chrome、Edge、Brave、Opera和Vivaldi中提供的面板可以评估核心Web重要指标并提出绩效建议:
相同的浏览器还提供了一个覆盖面板来帮助定位未使用的CSS属性,如红色边框所示:
请注意,未使用的样式指示符:
- 刷新或导航到新页面时重置,以及
- 计算一段时间内的样式使用情况。所需样式可能看起来未使用,因为未以特定方式查看或使用构件。
大多数DevTools还提供性能面板。它们最常用于JavaScript评估,但也可以在应用CSS时识别CPU和布局峰值。
在线性能工具还可以报告一系列CSS改进因素:
- 打开重放:https://www.openreplay.com/
- 谷歌PageSpeed洞察:https://pagespeed.web.dev/
- 网页测试
- [Pingdom网站速度测试:https://tools.pingdom.com/
2.快速间接改进CSS
您可以在不接触任何代码的情况下进行性能改进:
- 迁移到更好、更快的Web主机或考虑使用内容交付网络(CDN)
- 启用GZIP或更好的压缩
- 活动HTTP/2或更高版本
- 确保浏览器可以通过设置适当的HTTP头缓存CSS,例如 Expires, Last-Modified, and ETag.
3.预加载样式表
该<链接rel ="预加载">标记允许您在引用CSS之前启动下载。当样式表引用出现在其它资源之后,或者您已经嵌套了@导入指令:
!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- preload CSS file -->
<link rel="preload" href="styles.css" as="style" />
<!-- more code -->
<!-- use preloaded styles -->
<link rel="stylesheet" href="styles.css" />
4.删除未使用的样式和文件
删除所有不使用的样式表。您可能能够识别不再使用的页面、小部件或框架代码。如果您将样式表拆分为具有明确责任级别和适当文档的单独文件,则此任务会更容易。
以下工具可以通过分析HTML和CSS来识别冗余代码:
- 联合国中央支助系统:https://github.com/uncss/uncss
- 清除CSS:https://purgecss.com/
- 未使用CSS:https://unused-css.com/
单独的HTML分析通常是不够的,但是您可以配置白名单样式,比如那些由JavaScript激活的样式。
5.删除CSS攻击和回退
旧的代码库可能有一系列笨拙的IE黑客和后备,试图修复布局问题或启用现代CSS属性。该应用程序的最后一个版本是在十年前发布的,现在已不再受支持。是时候删除代码了。
即使你很不幸有很大比例的IE用户,许多CSS黑客使浏览器变慢。
6.使用fonts
使用OS字体可以保存数百KB,并避免出现诸如无样式文本闪烁(FOUT)或不可见文本闪烁(FOIT)等问题。您的用户可能根本不会注意到。当然,你的设计师会...
7.删除不必要的字体
标准字体需要为每种粗细和样式创建单独的文件。您可以删除那些不常用的。
同样,您不太可能需要字体中的所有字符和字形。可以使用以下工具生成字体子集字体松鼠或指定所需的字符谷歌字体例如,加载"OpenReplay"的Oswald字体字符:
<link href="https://fonts.googleapis.com/css2?family=Oswald&text=OpenReplay" rel="stylesheet">
您还可以考虑可变字体。它们使用矢量插值定义了各种样式、权重和斜体。该文件稍大,但只需要一种字体而不是多种字体。
8. Host font files locally
引用Google字体很容易,但额外的DNS查找、生成子集和跟踪使用情况会带来性能成本。本地托管字体的下载和呈现速度明显更快。
Web开放字体格式2.0(WOFF2)是您唯一需要的文件版本。所有现代浏览器都支持这种字体,IE用户可以回到OS字体。
您还应该在CSS中定义适当的字体显示加载选项。以下选项可提供明显的性能提升:
- 互换:使用第一个备用OS字体,直到Web字体可用。文本始终可读,但无样式文本的闪烁如果两个字符集具有不同的尺寸,则(FOUT)可能不一致。
- fallback:FOIT和FOUT之间的折衷方案。文本在100ms内不可见。然后使用Web字体(如果可用)。否则,它将恢复为交换。
- 可选:与回退相同,只是在下载Web字体后不进行字体交换。它应该出现在下一个页面加载。
9.使用HTML<链接>而不是CSS @导入
@ import at-rule允许您在CSS中加载样式表:
/* main.css */
@import url("reset.css");
@import url("base.css");
@import url("grid.css");
这允许您将样式表拆分为更小、更易于管理的样式表,但是每个@import都会阻塞渲染。浏览器必须依次下载和解析每个文件。
使用HTML<链接>标记效率更高,因为每个样式表都是并行加载的:
<link rel="stylesheet" href="reset.css">
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="grid.css">
或者...
10.捆绑和缩小样式表
HTTP/2可以比HTTP/1.1更好地服务于多个样式表,但是单个文件需要一个头,并且可以更有效地进行gzip压缩和缓存。您可以在开发过程中使用任意数量的文件,但是要使用构建步骤来捆绑和缩小到单个样式表中。包括Sass预处理器或PostCSS导入插件在内的工具可以在一个命令中完成这项艰巨的工作。
11.使用现代CSS布局
较早的布局技术,如浮动和,我敢说,HTML<表>是笨重的,难以管理,并需要大量的代码来管理间距和媒体查询。如果您的代码库中仍然有它们,那么是时候切换到:
- CSS列:https://developer.mozilla.org/docs/Learn/CSS/CSS_layout/Multiple-column_Layout。用于类似报纸的文本栏。
- CSS Flexbox:https://developer.mozilla.org/docs/Learn/CSS/CSS_layout/Flexbox.对于一维布局,可以选择换行到下一行。适用于菜单、图片库、卡片等。
- CSS网格:https://developer.mozilla.org/docs/Learn/CSS/CSS_layout/Grids。对于具有显式行和列的二维布局。非常适合页面布局。
所有这些都更易于开发,使用更少的代码,渲染更快,并且可以适应不同的屏幕大小,而无需媒体查询。
非常旧的浏览器不支持这些属性,它们将每个元素显示为一个标准块。这导致了一个更简单、更快的类似移动设备的线性布局,而且几乎没有理由添加后备。
12.用CSS效果替换图像
尽可能使用CSS代码生成图形,而不是引用图像。现代的浏览器为复杂的形状提供了渐变、带图案的边框、圆角、阴影、滤镜、叠加、混合模式、蒙版、剪切和伪元素。
CSS效果使用的带宽要少得多,可重复使用,易于修改,并且通常可以制作动画。
13.从不嵌入base64编码的位图
您可以使用base64编码将图像嵌入到CSS中,base64编码将像素转换为文本字符:
.imgbackground {
background-image: url('data:image/jpg;base64,0123456...');
}
该技术减少了HTTP请求,但可能会损害CSS性能:
- base64字符串通常比二进制数据大30
- 浏览器需要额外的步骤来解码字符串,并且
- 修改一个像素会使整个CSS文件无效,因此必须重新下载。
只有当图像很小,生成的字符串不比URL长多少时,才考虑base64编码。
14.尽可能使用SVG
“可缩放矢量图形”包含绘图指令,例如“在此点绘制一个半径为50个单位、红色填充和蓝色3个单位边框的圆”:
<svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 120 120">
<circle cx="60" cy="60" r="50" stroke-width="3" stroke="#00f" fill="#ff0" />
<svg>
它们是徽标和图表的理想选择,在任何分辨率下都很好看,并且文件大小应该比位图小。
在可行的情况下,您可以将SVG直接内联到CSS代码中:
.svgbackground {
background: url('data:image/svg+xml;utf8,<svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 120 120"><circle cx="60" cy="60" r="50" stroke-width="3" stroke="#00f" fill="#f0" /></svg>') center no-repeat;
}
这将增加样式表的大小,但对于必须立即显示的较小的可重用图标来说,这很有用。
15.使用CSS设置SVG样式
直接将SVG代码嵌入到HTML中通常更有用和有效,例如。
<main>
<svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 120 120">
<circle cx="60" cy="60" r="50" stroke-width="3" stroke="#00f" fill="#ff0" />
<svg>
</main>
这将SVG放入DOM中。SVG的属性具有低特异性,并且可以在CSS中覆盖:
/* change to green and black */
circle {
stroke-width: 10px;
stroke: #000;
fill: #0f0;
}
您可以:
- 从HTML中删除SVG样式属性
- 对不同的节或页使用具有不同样式的相同图像,以及
- 动画任何CSS属性。
开源会话重放
OpenReplay是一个开源会话回放套件,可让您查看用户在Web应用上执行的操作,从而帮助您更快地解决问题。OpenReplay是自托管的,可以完全控制您的数据。
开始享受调试体验-开始免费使用OpenReplay。
16.成为CSS框架的牺牲品
CSS框架在你开始web开发时是很有帮助的。他们提供了一套有吸引力的风格,所以你可以迅速成为生产力。缺点?......
- 框架可以包含大量代码,但您可能只使用了可用样式中的一小部分。在可能的情况下,检查您是否包含所需的功能,而不是更多。
- 当框架样式不完全符合您的需要时,覆盖框架样式可能会很有挑战性。结果是两组样式,而实际上只需要一组样式。
17.预处理代码生成
CSS预处理器(如Sass)通过提供变量、循环、函数和mixin等语言构造,使CSS开发受益匪浅。也就是说,一定要检查生成的代码,以确保它与您自己编写的代码一样简洁。特别是,深度嵌套的结构可能会导致过于复杂的选择器,从而使样式表变得庞大。
18.简化您的选择器
现代浏览器解析长选择器没有问题,但是降低复杂性将减小文件大小,提高性能,并使代码更易于维护。
您还应该考虑新的:is、:where和:has选择器,它们可以像这样转换CSS选择器:
article section.primary:not(:first-child) h1,
article section.primary:not(:first-child) h2,
article section.primary:not(:first-child) p,
article section.secondary:not(:first-child) h1,
article section.secondary:not(:first-child) h2,
article section.secondary:not(:first-child) p {
color: red;
}
变成一句简洁的话:
article section:not(:first-child):where(.primary, .secondary) :where(h1, h2, p) {
color: red;
}
19.避免昂贵的属性
某些CSS属性比其他属性需要更多的处理。将这段代码添加到样式表中,看看滚动是如何变得不稳定的!
*, ::before, ::after {
box-shadow: 3px 5px 5px rgba(0,0,0,0.3);
}
以下特性触发CPU密集型绘制计算:
- position: fixed
- border-radius
- box-shadow
- text-shadow
- opacity
- transform
- filter
- backdrop-filter
- background-blend-mode
这并不是说您不应该使用它们,但是在将这些属性应用于许多元素时要谨慎。
20.使用CSS转换和动画
CSS过渡和动画将比JavaScript支持的效果更平滑,后者改变了相同的属性。但是,最好避免对触发重新布局的属性进行动画处理,例如尺寸(宽度、高度、填充、边框)或位置(顶部、底部、左侧、右侧、边距)。这会导致整个页面在每个动画帧上重新布局。
有效的动画特性包括:
- opacity
- filter模糊、对比度、阴影等。
- transform:平移(移动)、缩放、旋转等。
浏览器可以使用硬件加速的GPU在自己的图层中渲染这些效果,这只会影响最终的合成渲染阶段。
通过使用将元素从页面流中取出,可以提高其他动画属性的性能位置:绝对。
21.用途意志改变必要时
该意志改变性质警告浏览器某个元素将以特定方式进行动画处理,以便浏览器可以提前进行优化:
.animatedelement {
will-change: transform, opacity;
}
可以设置任意数量的逗号分隔值。
改变意愿应该作为解决特定性能问题的最后手段。不应将其应用于太多的元素或在页面加载时立即启动动画。给予浏览器一点时间进行优化。
22. @transkey_groupall~trans
HTTP协议保存-数据标题指示用户已请求缩减的数据。浏览器可能会将此选项标记为"lite"或"turbo"模式,当启用此选项时,会显示保存-数据标头随每个浏览器请求一起发送:
GET /main.css HTTP/2.0
Host: mysite.com
Save-Data: on
服务器可以检测报头并相应地作出响应。例如,它可以提供更简单的CSS文件,该文件具有使用OS字体、块颜色和更少图像的线性布局。
服务器必须在修改请求时返回以下标头,以确保轻量级CSS文件在用户停用时不会被重用保存-数据:
Vary: Accept-Encoding, Save-Data
客户端JavaScript还可以检测保存-数据选项卡页面上创建或编辑条目.下面的代码添加全用户体验类添加到<超文本标记语言>元素时保存-数据是不启用:
if ('connection' in navigator && !navigator.connection.saveData) {
document.documentElement.classList.add('fullUX');
}
然后,样式表可以应用适当的样式,而无需任何服务器交互:
/* no hero image by default */
header {
background-color: #ceb;
background-image: none;
}
/* hero image when Save-Data is not enabled */
.fullUX header {
background-image: url('bigimg.jpg');
}
prefers-reduced-data media查询提供了一个仅CSS的替代方案,尽管目前还没有任何浏览器支持它:
/* no hero image by default */
header {
background-color: #ceb;
background-image: none;
}
/* hero image when no Save-Data */
@media (prefers-reduced-data: no-preference) {
header {
background-image: url('bigimg.jpg');
}
}
23.考虑关键内联CSS
Tools such as Lighthouse may recommend you "inline critical CSS" or "reduce render-blocking style sheets. " by:
- 标识页面加载时可见的折叠上方元素所使用的基本样式。
- 将关键CSS内联到 <style> tag in your <head>.
- 异步加载剩余的CSS以避免阻塞页面的呈现。
下面的示例将剩余的CSS作为"打印"样式表,浏览器以较低的优先级异步加载。该加载代码在下载后将其切换回所有媒体的标准样式表。该<诺斯克文>确保在未启用JavaScript的情况下仍然加载:
<head>
<!-- critical styles -->
<style>
body { font-family: sans-serif; color: #111; }
</style>
<!-- load remaining styles -->
<link rel="stylesheet" href="main.css" media="print" onload="this.media='all'">
<noscript>
<link rel="stylesheet" href="main.css">
</noscript>
<head>
该技术显著提高了性能,并可能有利于具有一致界面的网站或单页面应用程序。较大的站点可能更具挑战性:
- 要识别折叠是不可能的--每个设备都不一样。
- 具有不同页面布局的站点需要不同的关键CSS。
- 该技术只对用户的第一页加载有益。后续页面加载可以使用缓存的样式表,因此内联CSS是不必要的,并且会降低性能。
如果您有一个小型站点,可以可靠地自动化构建过程,或者有一个单页应用程序,请考虑关键的CSS。
24.创建针对设备的样式表
包含所有设备代码的单个(构建)样式表对于大多数站点都是实用的。然而,如果你的代码库很大,或者移动的和桌面设计有很大的不同,你可以创建特定于设备的样式表,例如。
<!-- core styles for all devices -->
<link rel="stylesheet" href="core.css">
<!-- served to screens less than 400px wide -->
<link rel="stylesheet" media="(max-width: 399px)" href="mobile.css">
<!-- served to screens 400px or wider -->
<link rel="stylesheet" media="(min-width: 400px)" href="desktop.css">
25.考虑CSS遏制
CSS包含通过允许您标识页的独立子树来提高性能。然后浏览器可以优化特定DOM内容块的呈现过程。
该集装箱属性支持以空格分隔的列表形式显示以下一个或多个值:
- none:无包含(默认)
- layout:将元素与页面的其余部分隔离:其内容不会影响其他元素的布局
- paint:将元素裁剪为特定大小而不出现任何可见溢出
- size:元素的行内和块尺寸与内容无关-无需计算子元素的大小
- inline-size:类似于 size but applies to inline dimensions only.
还提供了两个特定值:
- strict:应用所有包含规则,除了 none
- content:应用 layout and paint
考虑一个具有长<乌尔>列表设置为包含:严格;。更改任何子项的内容时<里>,浏览器将不会重新计算该项目、列表中的其他项目或页面上的任何其他元素的大小或位置。渲染速度更快。
26.尝试渐进式渲染
渐进式呈现是一种为每个页面和组件定义单独样式表的技术。这将有利于具有大量CSS的大型站点,这些站点的页面具有不同的设计或由一系列组件构成。
- 不需要在第一个页面加载时为不使用的组件下载一个包含CSS的大型样式表。
- 对一个组件的样式所做的更改不会影响其他缓存文件。
你可以领养原生Web组件或在组件出现在HTML中之前立即引用较小的CSS文件:
<body>
<!-- core styles -->
<link rel="stylesheet" href="core.css" />
<!-- header -->
<link rel="stylesheet" href="header.css" />
<header>header content</header>
<!-- article -->
<link rel="stylesheet" href="article.css" />
<main>
<h1>title</h1>
<!-- widget -->
<link rel="stylesheet" href="widget.css" />
<div class="widget">widget content</div>
</main>
<!-- footer -->
<link rel="stylesheet" href="footer.css" />
<footer>footer content</footer>
</body>
大多数浏览器在HTML下载时呈现HTML。每个样式表<链接>都是呈现阻止的,但每个文件不应超过几千字节。
较旧的浏览器可能会显示一个空白页面,直到所有CSS都加载完毕,但总体影响应该不会比一个大的呈现阻塞样式表更糟。
27.采用web组件
本机浏览器Web组件提供了一种创建封装的、单一责任的自定义功能的方法。换句话说,您可以创建自己的HTML标记,例如<hello-world>,它与每个框架都兼容。
JavaScript框架引入了这些概念,但它们的组件从未真正与其他CSS或JavaScript分离。原生组件提供了一个Shadow DOM,它隔离了元素,因此样式和功能不会泄漏。优点:
- 默认情况下,组件的CSS负责其样式。只有在使用该组件时才会下载和缓存它。
- 组件CSS可以比页面CSS更简洁,因为它不需要复杂的或特定于位置的选择器。
组件仍然可以显示shadow:part元素,因此可以进行有限的外部样式设置。
28.使用良好实践开发技术
良好实践技术会不断发展、过期,并且因开发人员而异,但可靠的方法包括:
- 将您的CSS组织成具有个人职责的较小文件,例如:页眉、页脚、表单元素、表格、菜单等。
- 使用linting工具和浏览器DevTools确保设置有效的属性和值。
- 使用以下工具自动化构建过程以构造单个样式表和自动刷新 浏览器同步.
- 采用移动优先的方法。默认样式创建更简单、线性、类似移动设备的布局。当空间允许时,媒体查询和固有的网格布局可以应用更复杂的桌面设计。
- 在移动的和桌面浏览器中彻底测试您的样式。至少,使用以下内容:
- 桌面:Firefox、Chrome(Chrome、Edge、Brave、Opera或Vivaldi)和Safari浏览器
- 移动的:Android上的Chrome和iOS上的Safari。
- 记录您的代码。您不会记得自己在一个月内做了什么--其他开发人员将如何科普!带有示例组件的样式指南是理想的选择。
29.拥抱瀑布
CSS新手通常会尝试绕过全局名称空间,并分别设置每个组件的样式。CSS-in-JS框架通常在构建时创建随机类名,因此组件样式不会冲突。
最后,使用CSS级联比使用CSS级联更好。例如,你可以设置默认字体、颜色、大小、边框等。它们是普遍应用的,然后在必要时覆盖它们。这样可以减少重复,缩短样式表的长度,提高样式表的性能。
30.学会爱上CSS
一知半解大有帮助。现代CSS的几行代码可以取代和改进十年前需要复杂JavaScript的效果。您对CSS了解得越多,需要编写的代码就越少。
诚然,CSS很容易学习,但掌握起来很有挑战性。没有人期望您理解数百个属性,但是当您下次在Stack Overflow或ChatGPT上找到解决方案时,逐步浏览代码是值得的。扎实掌握CSS基础知识可以彻底改变您的工作流程、增强您的应用程序并显著提高性能。
如果你正在学习css,为你整理了一套30天的课程体系,可以进入一起学习!
为帮助到一部分同学不走弯路,真正达到一线互联网大厂前端项目研发要求,首次实力宠粉,打造了《30天挑战学习计划》,内容如下:
HTML/HTML5,CSS/CSS3,JavaScript,真实企业项目开发,云服务器部署上线,从入门到精通
- PC端项目开发(1个)
- 移动WebApp开发(2个)
- 多端响应式开发(1个)
共4大完整的项目开发 !一行一行代码带领实践开发,实际企业开发怎么做我们就是怎么做。从学习一开始就进入工作状态,省得浪费时间。
从学习一开始就同步使用 Git 进行项目代码的版本的管理,Markdown 记录学习笔记,包括真实大厂项目的开发标准和设计规范,命名规范,项目代码规范,SEO优化规范
从蓝湖UI设计稿 到 PC端,移动端,多端响应式开发项目开发
- 真机调试,云服务部署上线;
- Linux环境下 的 Nginx 部署,Nginx 性能优化;
- Gzip 压缩,HTTPS 加密协议,域名服务器备案,解析;
- 企业项目域名跳转的终极解决方案,多网站、多系统部署;
- 使用 使用 Git 在线项目部署;
这些内容在《30天挑战学习计划》中每一个细节都有讲到,包含视频+图文教程+项目资料素材等。只为实力宠粉,真正一次掌握企业项目开发必备技能,不走弯路 !
过程中【不涉及】任何费用和利益,非诚勿扰 。
如果你没有添加助理老师微信,可以添加下方微信,说明要参加30天挑战学习计划,来自CSDN!老师会邀请你进入学习,并给你发放相关资料。
30 天挑战学习计划 Web 前端从入门到实战 | arry老师的博客-艾编程