12. 警惕耗时的属性
某些属性的渲染速度比其他属性要慢。如果想要增加页面的不流畅感,可以尝试在所有元素上添加盒子阴影!
*, ::before, ::after { box-shadow: 5px 5px 5px rgba(0,0,0,0.5); }
浏览器性能会有所不同,但总体来说,在绘制之前引起重新计算的任何操作都会在性能方面造成更大的开销:
有些属性在绘制之前引起重新计算的原因是因为它们会影响元素的布局和外观,导致浏览器需要重新计算并重新渲染受影响的部分。
- border-radius:
border-radius
属性用于设置元素的圆角边框。当更改此属性时,元素的形状会发生变化,可能会影响元素的周围元素的位置和排列,从而引起重新计算。 - box-shadow:
box-shadow
属性用于添加元素的阴影效果。更改此属性会影响元素的可视外观,可能导致元素的尺寸和位置发生变化,从而引起重新计算。 - opacity:
opacity
属性用于设置元素的透明度。更改此属性会影响元素的可视外观,可能会导致元素的尺寸和位置发生变化,从而引起重新计算。 - transform:
transform
属性用于应用元素的2D或3D转换效果,如旋转、缩放和平移。修改此属性可能会改变元素的位置、形状和大小,导致重新计算。 - filter:
filter
属性用于应用元素的图像滤镜效果,如模糊、对比度调整等。更改此属性可能会影响元素的可视外观,导致重新计算。 - position: fixed: 使用
position: fixed
将元素固定在视口中的特定位置,不会随页面滚动而移动。由于这会影响元素的定位,所以更改此属性可能会影响周围元素的位置和布局,从而引起重新计算。
13. 采用 CSS 动画
原生的CSS过渡和动画始终比使用JavaScript修改相同属性的效果要快。
然而,不要仅为了效果而使用动画。微妙的效果可以提升用户体验,而不会对性能产生不利影响。过多的动画可能会拖慢浏览器,并导致部分用户出现晕动感。
14. 避免为耗时的属性制作动画
对元素的尺寸或位置进行动画处理可能会导致整个页面在每一帧上重新布局。如果动画只影响合成阶段,性能可以得到改善。
这里就不得不提一下,合成层的概念了.
合成层
只有一些特殊的渲染层才会被提升为合成层,通常来说有这些情况:
transform:3D
变换:translate3d
,translateZ
;will-change:opacity | transform | filter
- 对
opacity
|transform
|fliter
应用了过渡和动画(transition/animation
) video、canvas、iframe
浏览器通常使用硬件加速的GPU来渲染这些效果。
关于这个可以看我们之前写的硬件加速
15. 指明哪些元素将成为动画
will-change
是一个用于优化性能的CSS属性,它允许开发者预先告知浏览器某个元素将会发生变化,从而让浏览器可以做出相应的优化准备。这可以帮助避免一些不必要的渲染和计算,提高页面的流畅性和响应速度。
具体来说,will-change
属性可以应用于一个或多个CSS属性,告知浏览器这些属性可能会在未来的某个时间点发生变化。浏览器可以根据这些信息进行一些优化,例如为元素创建独立的图层,从而在元素发生变化时只重新渲染图层,而不影响整个页面的渲染。
以下是使用示例:
.myelement { will-change: transform, opacity; }
在上面的示例中,我们告知浏览器 .myelement
元素的 transform
和 opacity
属性可能会发生变化。浏览器可以根据这些信息做出优化,例如将该元素放置在独立的图层中,以便在这些属性发生变化时能够更高效地进行渲染。
需要注意的是:
will-change
应该作为一种优化手段,而不是滥用。不要随意将所有元素都添加will-change
属性,因为这可能会导致不必要的内存消耗。will-change
应该在元素需要变化之前的一段时间内添加,而不是立即添加,以便浏览器有足够的时间进行优化准备。- 一些浏览器可能会忽略
will-change
,或者在某些情况下不起作用。因此,它应该被视为一种辅助性能优化手段,而不是必须的。
总之,will-change
属性可以帮助开发者在需要进行复杂动画或变换的情况下,提前通知浏览器进行性能优化,从而提高页面的响应性和流畅性。
需要注意事项
尽管 will-change
属性可以用于优化性能,但它并不是在所有情况下都会产生积极效果。在某些情况下,错误地使用 will-change
可能会导致性能问题,而不是改善。
以下是可能导致页面更卡顿的一些原因:
- 过度使用
will-change
: 如果过多的元素都被添加了will-change
属性,浏览器可能会创建大量的图层,导致内存占用增加,反而降低了性能。因此,应该谨慎使用,并只在真正需要优化的元素上添加。 - 属性变化频繁: 如果一个元素上添加了
will-change
属性,但该属性的变化频率很高,浏览器可能需要不断地重新创建图层,造成性能开销。在这种情况下,使用will-change
可能不是一个好的选择。 - GPU 资源受限: 一些设备可能具有受限的 GPU 资源,无法承载大量的图层和渲染操作。在这种情况下,添加过多的
will-change
属性可能会导致页面卡顿。 - 不合适的属性选择: 如果选择了不适当的属性添加到
will-change
中,浏览器可能会做出错误的优化。例如,添加了大量的will-change: transform
属性,但只有少数元素实际需要变换,这可能会导致性能下降。
示例代码如下:
.myelement { will-change: transform; transition: transform 0.3s ease; } .myelement:hover { transform: translateX(20px); }
在上面的示例中,当鼠标悬停在 .myelement
元素上时,会发生变换。如果元素频繁发生变换,而且同时使用了 will-change
和过渡效果,可能会导致页面卡顿。
因此,尽管 will-change
可以用于性能优化,但在使用时需要谨慎考虑上述因素,确保它被正确地应用在需要进行复杂变换或动画的元素上。如果添加了 will-change
后出现了性能问题,可以尝试移除它,看看是否有改善。
16. 采用 SVG 图像
可缩放矢量图形(SVG)通常用于标识、图表、图标和简单的图示。与JPG和PNG位图不同,SVG不会定义每个像素的颜色,而是在XML中定义形状,如线条、矩形和圆圈。例如:
<svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 800 600"> <circle cx="400" cy="300" r="50" stroke-width="5" stroke="#f00" fill="#ff0" /> <svg>
简单的SVG比等效的位图要小,并且可以无限缩放而不会失去清晰度。
SVG可以直接内联在CSS代码中作为背景图像。这对于较小、可重复使用的图标非常理想,并且避免了额外的HTTP请求。例如:
.mysvgbackground { background: url('data:image/svg+xml;utf8,<svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 800 600"><circle cx="400" cy="300" r="50" stroke-width="5" stroke="#f00" fill="#ff0" /></svg>') center center no-repeat; }
17. 用 CSS 制作 SVG 样式
更常见的情况是,SVG直接嵌入到HTML文档中:
<body> <svg class="mysvg" xmlns="https://www.w3.org/2000/svg" viewBox="0 0 800 600"> <circle cx="400" cy="300" r="50" /> <svg> </body>
这将SVG节点直接添加到DOM中。因此,所有的SVG样式属性都可以使用CSS来应用:
circle { stroke-width: 1em; } .mysvg { stroke-width: 5px; stroke: #f00; fill: #ff0; }
嵌入的SVG代码量减少,CSS样式可以根据需要进行重用或动画处理。
请注意,将SVG放在<img>
标签内或作为CSS背景图像使用会将它们与DOM分离,CSS样式将不会产生影响。
18. 避免使用 Base64 位图图像
标准的位图文件(JPG、PNG和GIF)可以在数据URI中编码为base64字符串。例如:
.myimg { background-image: url('data:image/png;base64,ABCDEFetc+etc+etc'); }
然而,不幸的是:
- base64编码通常比其二进制等效物要大约30%;
- 浏览器必须在使用之前解析字符串;
- 修改图像会使整个(缓存的)CSS文件无效。
尽管减少了HTTP请求,但它很少提供明显的好处,特别是在HTTP/2连接下。通常情况下,避免内联位图,除非图像不太可能经常更改,且生成的base64字符串不太可能超过几百个字符。
19. 考虑关键 CSS
那些使用谷歌页面分析工具的人通常会看到建议“内联关键CSS”或“减少渲染阻塞的样式表”。加载CSS文件会阻塞渲染,因此可以通过以下步骤来提高性能:
- 提取用于渲染视窗上方元素的样式。
- 将这些样式添加到HTML的
<head>
元素中的<style>
元素中。 - 使用JavaScript异步加载主要的CSS文件(可以在页面加载后加载)。
这种技术无疑可以提高性能,并且可能对具有一致界面的渐进式Web应用程序或单页面应用程序有所益处。
20. 考虑渐进式渲染
渐进式渲染(Progressive Rendering)是一种优化策略,旨在改善网页加载和渲染性能,以提供更好的用户体验。通过渐进式渲染,页面的内容可以在加载过程中逐步呈现给用户,使用户能够更快地看到页面的部分内容,而不必等待整个页面完全加载和渲染。
渐进式渲染的主要思想是将页面内容分为多个阶段,并在加载过程中逐步完成这些阶段,从而实现快速呈现。以下是渐进式渲染的一些关键概念和技术:
- 分段加载内容: 将页面内容划分为多个模块或组件,并按照优先级逐步加载。通常,首屏内容、核心内容和附加内容可以分别进行加载。
- 优先加载关键资源: 首先加载对页面呈现至关重要的关键资源,例如文本内容、主要图像和交互所需的脚本。这可以使用户更快地看到页面的主要内容。
- 延迟加载次要资源: 对于一些不是首要显示的资源,如下方的图像、广告、辅助内容等,可以采用延迟加载的方式,使页面更快地完成加载和呈现。
- 分块渲染: 将页面内容分为不同的块或区域,并在加载完成每个块后立即呈现。这样,即使页面的某些部分尚未完全加载,用户仍然可以浏览已经呈现出来的内容。
- 懒加载: 对于一些不在首屏或不在用户视线范围内的内容,可以使用懒加载技术。这意味着只有当用户滚动到相应区域时才加载内容,从而减少初始加载时间。
- 逐步呈现动画: 对于页面上的动画效果,可以使用渐进式呈现,以使动画更早地出现并逐步完善。这可以避免用户在等待动画加载时的空白时间。
分段加载内容
与使用单个整站CSS文件不同,渐进式渲染是一种为单独的组件定义独立样式表的技术。每个样式表会在HTML中引用组件之前立即加载:
<head> <!-- 适用于各个组件的核心样式 --> <link rel='stylesheet' href='base.css' /> </head> <body> <!-- 头部组件 --> <link rel='stylesheet' href='header.css' /> <header>...</header> <!-- 主要内容 --> <link rel='stylesheet' href='content.css' /> <main> <!-- 表单样式 --> <link rel='stylesheet' href='form.css' /> <form>...</form> </main> <!-- 底部组件 --> <link rel='stylesheet' href='footer.css' /> <footer>...</footer> </body>
每个<link>
仍然会阻止渲染,但时间较短,因为文件较小。页面会更早可用,因为每个组件按顺序渲染;页面顶部的内容可以在剩余内容加载时被查看。
懒加载
假设我们有一个包含多个段落的网页,我们将通过分块加载和渲染逐步显示这些段落。
<!DOCTYPE html> <html lang="en"> <head> <style> /* 初始化时只显示第一个段落 */ .hidden { display: none; } </style> <script> // 模拟页面加载和渲染 function simulateProgressiveRendering() { const paragraphs = document.querySelectorAll('.hidden'); let currentIndex = 0; function showNextParagraph() { if (currentIndex < paragraphs.length) { paragraphs[currentIndex].style.display = 'block'; currentIndex++; requestAnimationFrame(showNextParagraph); } } // 开始加载和渲染 showNextParagraph(); } </script> </head> <body onload="simulateProgressiveRendering()"> <p class="hidden">段落1</p> <p class="hidden">段落2</p> <p class="hidden">段落3</p> <p class="hidden">段落4</p> </body> </html>
渐进式渲染可能对大型网站有益,其中每个页面由不同组件的选择构建。
寄语
针对前端开发工程师来说, CSS
是我们再熟悉不过的老朋友了,但是由于它体系的庞杂和多边性,导致我们总是有一种力不从心的感觉.
但是,如果你要想成为一个合格的前端工程师,CSS
的也是一道必选题. 我们需要不断的去理解不断的去实践.
这里,就不得不推荐,张鑫旭大佬的书籍了. 有时候,不是我们不用功,而是我们陷入了一种弯路.
后记
分享是一种态度。
全文完,既然看到这里了,如果觉得不错,随手点个赞和“在看”吧。