根据httparchive.org的页面重量报告,CSS在平均70个请求和2MB的网页上占7个HTTP请求和70Kb的代码。这并不是网站性能糟糕的最坏原因(我正看着你呢,JavaScript),但CSS面临着特定的挑战:
下面的30个技巧将帮助您优化CSS,以改善实际和感知的响应时间。
衡量是确定业绩机会和评估收益的唯一途径。所有浏览器都提供DevTools面板,通常通过“更多工具”菜单或键盘快捷键Ctrl打开|按下Cmd + Shift +i或F12组合键。
“网络”面板是一个很好的起点,刷新后,它会显示资源下载的瀑布图:
较长的条突出显示加载缓慢或渲染受阻的资源(如上图中的白色块所示)。
该灯塔Chrome、Edge、Brave、Opera和Vivaldi中提供的面板可以评估核心Web重要指标并提出绩效建议:
相同的浏览器还提供了一个覆盖面板来帮助定位未使用的CSS属性,如红色边框所示:
请注意,未使用的样式指示符:
大多数DevTools还提供性能面板。它们最常用于JavaScript评估,但也可以在应用CSS时识别CPU和布局峰值。
在线性能工具还可以报告一系列CSS改进因素:
您可以在不接触任何代码的情况下进行性能改进:
该<链接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" />
删除所有不使用的样式表。您可能能够识别不再使用的页面、小部件或框架代码。如果您将样式表拆分为具有明确责任级别和适当文档的单独文件,则此任务会更容易。
以下工具可以通过分析HTML和CSS来识别冗余代码:
单独的HTML分析通常是不够的,但是您可以配置白名单样式,比如那些由JavaScript激活的样式。
旧的代码库可能有一系列笨拙的IE黑客和后备,试图修复布局问题或启用现代CSS属性。该应用程序的最后一个版本是在十年前发布的,现在已不再受支持。是时候删除代码了。
即使你很不幸有很大比例的IE用户,许多CSS黑客使浏览器变慢。
使用OS字体可以保存数百KB,并避免出现诸如无样式文本闪烁(FOUT)或不可见文本闪烁(FOIT)等问题。您的用户可能根本不会注意到。当然,你的设计师会...
标准字体需要为每种粗细和样式创建单独的文件。您可以删除那些不常用的。
同样,您不太可能需要字体中的所有字符和字形。可以使用以下工具生成字体子集字体松鼠或指定所需的字符谷歌字体例如,加载"OpenReplay"的Oswald字体字符:
<link href="https://fonts.googleapis.com/css2?family=Oswald&text=OpenReplay" rel="stylesheet">
您还可以考虑可变字体。它们使用矢量插值定义了各种样式、权重和斜体。该文件稍大,但只需要一种字体而不是多种字体。
引用Google字体很容易,但额外的DNS查找、生成子集和跟踪使用情况会带来性能成本。本地托管字体的下载和呈现速度明显更快。
Web开放字体格式2.0(WOFF2)是您唯一需要的文件版本。所有现代浏览器都支持这种字体,IE用户可以回到OS字体。
您还应该在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">
或者...
HTTP/2可以比HTTP/1.1更好地服务于多个样式表,但是单个文件需要一个头,并且可以更有效地进行gzip压缩和缓存。您可以在开发过程中使用任意数量的文件,但是要使用构建步骤来捆绑和缩小到单个样式表中。包括Sass预处理器或PostCSS导入插件在内的工具可以在一个命令中完成这项艰巨的工作。
较早的布局技术,如浮动和,我敢说,HTML<表>是笨重的,难以管理,并需要大量的代码来管理间距和媒体查询。如果您的代码库中仍然有它们,那么是时候切换到:
所有这些都更易于开发,使用更少的代码,渲染更快,并且可以适应不同的屏幕大小,而无需媒体查询。
非常旧的浏览器不支持这些属性,它们将每个元素显示为一个标准块。这导致了一个更简单、更快的类似移动设备的线性布局,而且几乎没有理由添加后备。
尽可能使用CSS代码生成图形,而不是引用图像。现代的浏览器为复杂的形状提供了渐变、带图案的边框、圆角、阴影、滤镜、叠加、混合模式、蒙版、剪切和伪元素。
CSS效果使用的带宽要少得多,可重复使用,易于修改,并且通常可以制作动画。
您可以使用base64编码将图像嵌入到CSS中,base64编码将像素转换为文本字符:
.imgbackground {
background-image: url('data:image/jpg;base64,0123456...');
}
该技术减少了HTTP请求,但可能会损害CSS性能:
只有当图像很小,生成的字符串不比URL长多少时,才考虑base64编码。
“可缩放矢量图形”包含绘图指令,例如“在此点绘制一个半径为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;
}
这将增加样式表的大小,但对于必须立即显示的较小的可重用图标来说,这很有用。
直接将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;
}
您可以:
OpenReplay是一个开源会话回放套件,可让您查看用户在Web应用上执行的操作,从而帮助您更快地解决问题。OpenReplay是自托管的,可以完全控制您的数据。
开始享受调试体验-开始免费使用OpenReplay。
CSS框架在你开始web开发时是很有帮助的。他们提供了一套有吸引力的风格,所以你可以迅速成为生产力。缺点?......
CSS预处理器(如Sass)通过提供变量、循环、函数和mixin等语言构造,使CSS开发受益匪浅。也就是说,一定要检查生成的代码,以确保它与您自己编写的代码一样简洁。特别是,深度嵌套的结构可能会导致过于复杂的选择器,从而使样式表变得庞大。
现代浏览器解析长选择器没有问题,但是降低复杂性将减小文件大小,提高性能,并使代码更易于维护。
您还应该考虑新的: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;
}
某些CSS属性比其他属性需要更多的处理。将这段代码添加到样式表中,看看滚动是如何变得不稳定的!
*, ::before, ::after {
box-shadow: 3px 5px 5px rgba(0,0,0,0.3);
}
以下特性触发CPU密集型绘制计算:
这并不是说您不应该使用它们,但是在将这些属性应用于许多元素时要谨慎。
CSS过渡和动画将比JavaScript支持的效果更平滑,后者改变了相同的属性。但是,最好避免对触发重新布局的属性进行动画处理,例如尺寸(宽度、高度、填充、边框)或位置(顶部、底部、左侧、右侧、边距)。这会导致整个页面在每个动画帧上重新布局。
有效的动画特性包括:
浏览器可以使用硬件加速的GPU在自己的图层中渲染这些效果,这只会影响最终的合成渲染阶段。
通过使用将元素从页面流中取出,可以提高其他动画属性的性能位置:绝对。
该意志改变性质警告浏览器某个元素将以特定方式进行动画处理,以便浏览器可以提前进行优化:
.animatedelement {
will-change: transform, opacity;
}
可以设置任意数量的逗号分隔值。
改变意愿应该作为解决特定性能问题的最后手段。不应将其应用于太多的元素或在页面加载时立即启动动画。给予浏览器一点时间进行优化。
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');
}
}
Tools such as Lighthouse may recommend you "inline critical CSS" or "reduce render-blocking style sheets. " by:
下面的示例将剩余的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。
包含所有设备代码的单个(构建)样式表对于大多数站点都是实用的。然而,如果你的代码库很大,或者移动的和桌面设计有很大的不同,你可以创建特定于设备的样式表,例如。
<!-- 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">
CSS包含通过允许您标识页的独立子树来提高性能。然后浏览器可以优化特定DOM内容块的呈现过程。
该集装箱属性支持以空格分隔的列表形式显示以下一个或多个值:
还提供了两个特定值:
考虑一个具有长<乌尔>列表设置为包含:严格;。更改任何子项的内容时<里>,浏览器将不会重新计算该项目、列表中的其他项目或页面上的任何其他元素的大小或位置。渲染速度更快。
渐进式呈现是一种为每个页面和组件定义单独样式表的技术。这将有利于具有大量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都加载完毕,但总体影响应该不会比一个大的呈现阻塞样式表更糟。
本机浏览器Web组件提供了一种创建封装的、单一责任的自定义功能的方法。换句话说,您可以创建自己的HTML标记,例如<hello-world>,它与每个框架都兼容。
JavaScript框架引入了这些概念,但它们的组件从未真正与其他CSS或JavaScript分离。原生组件提供了一个Shadow DOM,它隔离了元素,因此样式和功能不会泄漏。优点:
组件仍然可以显示shadow:part元素,因此可以进行有限的外部样式设置。
良好实践技术会不断发展、过期,并且因开发人员而异,但可靠的方法包括:
CSS新手通常会尝试绕过全局名称空间,并分别设置每个组件的样式。CSS-in-JS框架通常在构建时创建随机类名,因此组件样式不会冲突。
最后,使用CSS级联比使用CSS级联更好。例如,你可以设置默认字体、颜色、大小、边框等。它们是普遍应用的,然后在必要时覆盖它们。这样可以减少重复,缩短样式表的长度,提高样式表的性能。
一知半解大有帮助。现代CSS的几行代码可以取代和改进十年前需要复杂JavaScript的效果。您对CSS了解得越多,需要编写的代码就越少。
诚然,CSS很容易学习,但掌握起来很有挑战性。没有人期望您理解数百个属性,但是当您下次在Stack Overflow或ChatGPT上找到解决方案时,逐步浏览代码是值得的。扎实掌握CSS基础知识可以彻底改变您的工作流程、增强您的应用程序并显著提高性能。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。