结合现代网站的复杂性和浏览器处理CSS的方式,即使少量的CSS也可能成为有限设备、网络延迟、带宽或数据限制的瓶颈。由于性能是用户体验的重要组成部分,因此确保在各种形状和大小的设备上获得一致、高质量的体验也需要优化您的CSS。这篇文章将介绍CSS可能导致的性能问题,以及使CSS不妨碍人们使用的最佳实践。目录CSS是如何工作的?注意CSS的大小优先考虑关键CSS使用高效的CSS动画使用CSS优化字体加载不要担心CSS选择器的速度。CSS是如何工作的?CSS阻止呈现当页面有CSS可用时,无论是内联样式表还是外部样式表,浏览器都会延迟呈现,直到CSS被解析。这是因为没有CSS的页面通常无法使用。如果浏览器向您显示一个没有CSS的混乱页面,片刻之后又返回到样式化的页面,那么不断变化的内容和突然的视觉变化会混淆用户体验。这种糟糕的用户体验有一个名字——无样式内容闪现(FOUC)。CSS可以阻止HTML的解析虽然浏览器在完成解析CSS之前不会显示内容,但它会处理其余的HTML。但是脚本会阻止解析器,除非它们被标记为延迟或异步。脚本有可能操纵页面和其余代码,因此浏览器必须知道脚本何时执行。解析器阻止脚本:脚本如何阻止HTML解析。因为脚本会影响应用到页面的样式,如果浏览器仍在处理一些CSS,它会等到完成后再运行脚本。因为在脚本运行之前解析文档不会继续,这意味着CSS不再只是阻止呈现——根据文档中外部样式表和脚本的顺序,它可能还会停止HTML解析。解析器阻止CSS:CSS如何阻止HTML解析。为避免阻塞解析,请尽快交付CSS,并以最佳顺序排列您的资产。注意CSS大小压缩和最小化CSS建立连接以下载外部样式表不可避免地会导致延迟,但是您可以通过最小化通过网络传输的总字节数来加快下载速度。压缩文件可以显着提高速度,许多托管平台和CDN将默认对资产进行压缩编码(或者您可以轻松配置)。服务器和客户端交互使用最广泛的压缩格式是Gzip。还有Brotli,它提供更好的压缩,尽管它不像Gzip那样得到很好的支持。缩小是删除空格和任何不必要代码的过程。输出是浏览器可以解析的较小但完全有效的代码文件,这将为您节省一些字节。Terser是一种流行的JavaScript缩小器,如果您使用webpack,v4包含一个插件来创建缩小的构建文件。调整:删除未使用的CSS使用CSS框架时,以未使用的CSS结束是相对常见的(除非我们只包含我们需要的组件)。大型代码库的长期增长也会出现同样的问题。删除未使用的CSS通常是一个手动过程。主要的挑战是它有多复杂。我们必须仔细检查整个网站(以覆盖媒体查询),在所有可能的状态下,在所有可能的设备上,并执行所有可能改变样式的JavaScript函数。UnusedCSS和PurifyCSS是流行的工具,可以帮助查明不必要的样式,但我们应该将它们与仔细的视觉回归测试结合使用。在这里,使用CSS-in-JS的显着优势是:每个组件中呈现的样式只需要CSS。在CSS-in-JS中加速CSS的秘诀是将CSS内联到页面中,或者将其提取到外部CSS文件中。将CSS发送到JavaScript文件会导致其解析和计算缓慢。优先考虑关键CSS关键CSS是一种提取和内联CSS以获得页面上方内容的技术。在HTML文档的
中内联提取样式,无需额外请求来获取它们并加快渲染速度。你知道吗?首屏是指浏览者在滚动之前在页面加载时看到的所有内容。由于存在多种设备和屏幕尺寸,因此对于所谓的首屏,没有统一定义的像素高度。为了尽量减少到第一个渲染的往返次数,请将上面的内容保持在14KB(压缩)以下。确定关键CSS并不完全准确,因为您需要对折叠位置做出假设(折叠位置因设备屏幕尺寸而异)。这对于高度动态的网站来说可能很困难。即使它不精确,它仍然可以带来性能提升,我们可以使用Critical、CriticalCSS和Penthouse等工具将其自动化。异步加载CSS其余的CSS(不太重要的部分)最好异步加载。这是通过将链接媒体属性设置为打印来实现的。
"Print"媒体类型定义了用户尝试打印时的样式表规则page,browse浏览器将加载此类样式表而不会延迟页面呈现。样式表加载完成后,将该样式表应用于所有媒体(即屏幕,而不仅仅是打印),使用onload属性将媒体设置为全部。另一种方法是使用(而不是rel="styleheet")来实现类似的模式,并在加载事件中将rel属性切换为styleheet。使用此方法时需要考虑一些缺点。浏览器对预加载的支持不是很好,因此需要polyfill(或使用loadCSS等库)跨浏览器应用样式表。预加载会很早地获取优先级最高的文件,可能会降低其他重要下载的优先级。如果你真的想要预加载提供的高优先级抓取(在支持它的浏览器中),loadCSS的创建者建议你将它与第一种模式结合起来,就像这样。避免在CSS文件中使用@import在CSS文件中使用@import会减慢渲染速度。首先,浏览器必须下载CSS文件以发现导入的资源,然后在渲染之前再次请求下载它。如果你有一个包含@importurl(import.css)的样式表;网络瀑布看起来像这样。在link元素中加载两个样式表,允许并行下载。使用高效的CSS动画当您为页面上的元素设置动画时,浏览器通常必须重新计算它们在文档中的位置和大小,从而触发布局。例如,如果您更改某个元素的宽度,则它的任何子元素都可能受到影响,并且页面布局的很大一部分可能会发生变化。布局几乎总是应用于整个文档,因此布局树越大,执行布局计算所需的时间就越长。动画元素时,布局和重绘必须最小化。并非所有CSS动画技术都是一样的,现代浏览器最适合使用位置、比例、旋转和不透明度来创建高性能动画。不要更改高度和宽度属性,而是使用transform:scale()代替。要移动元素,请避免更改top、right、bottom或left属性,而应使用transform:translate()代替。如果您想模糊背景,请考虑使用模糊图像并更改其不透明度。调整:contain属性containCSS属性告诉浏览器该元素及其子元素被认为独立于文档树(尽可能)。它将页面的子树与其余部分隔离开来。这允许浏览器优化页面各个部分的呈现(样式、布局和绘制操作)以提高性能。contain属性在包含许多单独小部件的页面上很有用。这可用于防止每个小部件内的更改在小部件的边界框外产生副作用。一个主要是静态的网站不会从这个策略中受益。使用CSS优化字体加载加载字体时避免不可见文本字体通常需要一段时间才能加载大文件。某些浏览器通过在字体加载之前隐藏文本来处理此问题(导致“不可见文本闪烁”或FOIT)。在优化速度时,您需要避免“不可见文本的闪烁”并使用系统字体(机器上预装的字体)立即向人们呈现内容。加载字体文件后,它会替换称为“不规则文本闪烁”或FOUT的系统字体。实现此目的的一种方法是使用字体显示——一种用于指定字体显示策略的API。使用带值交换的字体显示告诉浏览器使用此字体的文本应立即使用系统字体显示。.使用可变字体来减小文件大小。可变字体可以将一种字体的许多不同变体组合到一个文件中,而不是为每种宽度、粗细或样式创建一个单独的字体文件。它们允许您通过CSS和@font-face引用访问给定字体文件中的所有更改。当您需要多种字体时,可变字体可以显着减小文件大小。您可以加载包含所有信息的单个文件,而不是加载常规和粗体样式以及它们的斜体版本。Monotype进行了一项实验,将12种输入字体组合在一起,生成3种宽度、斜体和罗马字体的8种权重。在一个可变字体文件中存储48种单独的字体意味着文件大小减少了88%。不要担心CSS选择器的速度。CSS选择器的结构方式会影响浏览器匹配它们的速度。浏览器从右到左读取选择器,因此当您使用后代选择器时。比如nava{},它会先匹配页面上的每一个元素,然后将nav里面的元素归零。如果您使用更具体的选择器,例如.nav-link在nav元素内的每个上,它不会花时间来匹配页面上的每个。如果您考虑浏览器如何从右到左匹配选择器,例如.containerullia{},您就会明白为什么后代选择器通常被标记为“昂贵”。这样的选择器似乎是一个速度问题。但是,选择器匹配性能很快。CSS声明对压缩算法非常友好,因此优化CSS选择器所需的工作通常最好花在应用程序的其他部分,投资回报率更高。CSS对于加载页面和愉快的用户体验至关重要。虽然我们可能经常优先考虑其他资源,例如脚本或图像,因为它们更具影响力,但我们不应该忘记CSS。通过上述策略,您将能够确保快速交付和执行。