CSS 性能优化
性能优化简介
CSS性能优化是指通过优化CSS代码和加载方式,提高页面渲染速度和用户体验。
选择器优化
1. 避免使用通配符选择器
css
/* 不好的做法 */
* {
margin: 0;
padding: 0;
}
/* 好的做法 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}2. 避免使用深层嵌套选择器
css
/* 不好的做法 */
.container .header .nav .menu .item {
color: blue;
}
/* 好的做法 */
.nav-item {
color: blue;
}3. 使用类选择器代替标签选择器
css
/* 不好的做法 */
div {
color: blue;
}
/* 好的做法 */
.container {
color: blue;
}4. 避免使用属性选择器进行正则匹配
css
/* 不好的做法 */
a[href^="https://"] {
color: blue;
}
/* 好的做法 */
.external-link {
color: blue;
}5. 使用更具体的选择器
css
/* 不好的做法 */
div {
color: blue;
}
/* 好的做法 */
.button-primary {
color: blue;
}CSS 加载优化
1. 减少CSS文件大小
css
/* 压缩CSS */
.button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
/* 压缩后 */
.button{padding:10px 20px;background-color:#007bff;color:white;border:none;border-radius:4px;cursor:pointer}2. 使用CSS压缩工具
bash
# 使用cssnano
npm install cssnano-cli --save-dev
# 压缩CSS
cssnano input.css output.css3. 合并CSS文件
html
<!-- 不好的做法 -->
<link rel="stylesheet" href="reset.css">
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="components.css">
<!-- 好的做法 -->
<link rel="stylesheet" href="main.css">4. 异步加载CSS
html
<!-- 使用media属性 -->
<link rel="stylesheet" href="print.css" media="print">
<!-- 使用JavaScript异步加载 -->
<script>
function loadCSS(href) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = href;
document.head.appendChild(link);
}
window.addEventListener('load', function() {
loadCSS('async.css');
});
</script>5. 内联关键CSS
html
<style>
.header {
background-color: #333;
color: white;
padding: 20px;
}
</style>渲染性能优化
1. 使用 transform 和 opacity
css
/* 不好的做法 */
.element {
left: 0;
transition: left 0.3s ease;
}
.element:hover {
left: 10px;
}
/* 好的做法 */
.element {
transform: translateX(0);
transition: transform 0.3s ease;
}
.element:hover {
transform: translateX(10px);
}2. 避免使用 width 和 height 进行动画
css
/* 不好的做法 */
.element {
width: 100px;
transition: width 0.3s ease;
}
.element:hover {
width: 200px;
}
/* 好的做法 */
.element {
transform: scaleX(1);
transform-origin: left;
transition: transform 0.3s ease;
}
.element:hover {
transform: scaleX(2);
}3. 使用 will-change 提示浏览器
css
.element {
will-change: transform, opacity;
}
.element:hover {
transform: translateX(10px);
}4. 避免布局抖动
css
/* 不好的做法 */
.element {
position: static;
transition: all 0.3s ease;
}
.element:hover {
margin-left: 10px;
}
/* 好的做法 */
.element {
position: relative;
transition: transform 0.3s ease;
}
.element:hover {
transform: translateX(10px);
}5. 使用硬件加速
css
.element {
transform: translateZ(0);
will-change: transform;
}图片优化
1. 使用合适的图片格式
html
<!-- WebP格式 -->
<picture>
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="图片">
</picture>2. 使用响应式图片
html
<img src="small.jpg"
srcset="small.jpg 480w, medium.jpg 768w, large.jpg 1024w"
sizes="(max-width: 480px) 480px, (max-width: 768px) 768px, 1024px"
alt="响应式图片">3. 懒加载图片
html
<img src="placeholder.jpg"
data-src="image.jpg"
alt="图片"
loading="lazy">
<script>
const images = document.querySelectorAll('img[data-src]');
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
images.forEach(img => imageObserver.observe(img));
</script>字体优化
1. 使用系统字体
css
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}2. 使用 font-display
css
@font-face {
font-family: 'MyFont';
src: url('myfont.woff2') format('woff2');
font-display: swap;
}3. 预加载字体
html
<link rel="preload" href="myfont.woff2" as="font" type="font/woff2" crossorigin>4. 使用字体子集
bash
# 使用fonttools
pip install fonttools
# 提取字体子集
pyftsubset myfont.ttf --text="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"代码优化
1. 避免重复代码
css
/* 不好的做法 */
.button-primary {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.button-secondary {
padding: 10px 20px;
background-color: #6c757d;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
/* 好的做法 */
.button {
padding: 10px 20px;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.button-primary {
background-color: #007bff;
}
.button-secondary {
background-color: #6c757d;
}2. 使用CSS变量
css
:root {
--primary-color: #007bff;
--secondary-color: #6c757d;
--font-size-base: 16px;
--spacing-unit: 8px;
}
.button {
padding: calc(var(--spacing-unit) * 1.25) calc(var(--spacing-unit) * 2.5);
background-color: var(--primary-color);
font-size: var(--font-size-base);
}3. 使用简写属性
css
/* 不好的做法 */
.button {
margin-top: 10px;
margin-right: 20px;
margin-bottom: 10px;
margin-left: 20px;
}
/* 好的做法 */
.button {
margin: 10px 20px;
}4. 移除未使用的CSS
bash
# 使用PurgeCSS
npm install purgecss --save-dev
# 移除未使用的CSS
purgecss --css styles.css --content index.html --output output.css浏览器优化
1. 使用CSS containment
css
.card {
contain: layout style paint;
}2. 使用content-visibility
css
.section {
content-visibility: auto;
contain-intrinsic-size: 1000px;
}3. 避免使用@import
html
<!-- 不好的做法 -->
<style>
@import url('styles.css');
</style>
<!-- 好的做法 -->
<link rel="stylesheet" href="styles.css">4. 使用媒体查询优化
css
/* 不好的做法 */
@media (min-width: 768px) {
.container {
width: 750px;
}
}
@media (min-width: 992px) {
.container {
width: 970px;
}
}
@media (min-width: 1200px) {
.container {
width: 1170px;
}
}
/* 好的做法 */
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}实际应用
1. 关键CSS内联
html
<!DOCTYPE html>
<html>
<head>
<style>
.header {
background-color: #333;
color: white;
padding: 20px;
}
.nav {
display: flex;
gap: 20px;
}
</style>
<link rel="preload" href="main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="main.css"></noscript>
</head>
<body>
<header class="header">
<nav class="nav">
<a href="/">首页</a>
<a href="/about">关于</a>
</nav>
</header>
</body>
</html>2. 图片懒加载
html
<img src="placeholder.jpg"
data-src="image.jpg"
alt="图片"
loading="lazy"
class="lazy-image">
<style>
.lazy-image {
opacity: 0;
transition: opacity 0.3s ease;
}
.lazy-image.loaded {
opacity: 1;
}
</style>
<script>
const lazyImages = document.querySelectorAll('.lazy-image');
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.onload = () => img.classList.add('loaded');
observer.unobserve(img);
}
});
});
lazyImages.forEach(img => imageObserver.observe(img));
</script>面试常见问题
1. 如何优化CSS性能?
- 优化选择器
- 减少CSS文件大小
- 使用transform和opacity
- 避免布局抖动
- 使用will-change
- 懒加载图片
- 使用CSS变量
2. 为什么使用transform代替left/top?
transform不会触发重排,只会触发重绘,性能更好。
css
/* 不好的做法 */
.element {
left: 0;
transition: left 0.3s ease;
}
/* 好的做法 */
.element {
transform: translateX(0);
transition: transform 0.3s ease;
}3. 什么是重排和重绘?
- 重排(Reflow): 元素的位置、大小发生变化
- 重绘(Repaint): 元素的外观发生变化
4. 如何避免重排?
- 使用transform代替left/top
- 使用opacity代替display
- 使用will-change提示浏览器
- 避免频繁读取布局信息
5. 什么是关键CSS?
关键CSS是首屏渲染所需的CSS,应该内联到HTML中,加快首屏渲染速度。
html
<style>
.header {
background-color: #333;
color: white;
}
</style>通过理解CSS性能优化的各种技术和最佳实践,可以创建高性能的网页。