跳到主要内容

工程与架构✅

什么是 CSS 工程化?

答案

CSS 工程化是旨提升 CSS 代码的可维护性、可复用性等的一系列实践和方法论。设计如下核心逻辑

  • 命名和组织,例如
    • BEM(块-元素-修饰符)贴近组件风格,按照模块/元素/修饰符的方式命名
    • Atomic(原子化)— 将样式拆分为最小不可分的原子单元,tailwind css 就是一个原子化的框架
    • OOCSS(面向对象的CSS)— 通过CSS“对象”分离容器和内容
    • SMACSS(可扩展和模块化的CSS架构)— 将CSS规则分为五类的风格指南,更细化的组织包括
      • BASE — 全局元素样式
      • LAYOUT — 布局样式
      • MODULE — 组件样式
      • STATE — 状态样式
      • THEME — 主题样式
  • 模块化,涉及预处理器/后处理器
    • Sass/SCSS/Less/Stylus 支持变量、嵌套、混入、函数等
    • PostCSS 支持自动添加浏览器前缀、变量、嵌套等
  • 逻辑复用框架
    • CSS Modules 支持局部作用域和可组合性
    • CSS-in-JS(如 Styled Components、Emotion) 支持动态样式和组件化
    • Utility-First 框架(如 Tailwind CSS) 提供大量原子类
    • 设计系统(如 Material-UI、Ant Design) 提供统一的设计规范和组件库
  • 构建/性能等
    • Webpack、Rollup、Vite 等打包工具 支持 CSS 预处理、后处理、Tree Shaking 等
    • CSS 构建工具(PurgeCSS) — 删除未使用的 CSS
    • lint 工具(如 stylelint) — 代码风格检查

延伸阅读

用过哪些 CSS 预处理器?

答案

CSS 预处理器是对 CSS 语言的扩展,提供了变量、嵌套、混入、函数等功能,使得 CSS 更加灵活和可维护。

常见的 CSS 预处理器包括:

  • Sass/SCSS:最流行的预处理器,支持变量、嵌套、混入、函数等。SCSS 是 Sass 的一种语法,是 CSS3 的超集,语法更接近 CSS。
  • Less:另一个流行的预处理器,语法类似于 Sass,支持变量、嵌套、混入等。
  • Stylus:一个功能强大的预处理器,支持更灵活的语法和功能,如函数、条件语句等。

这里以 Stylus 为例说明常用核心功能

核心功能说明
变量直接定义变量,无需特殊符号,如 primaryColor = #3498db,使用时直接写变量名,如 background-color: primaryColor。支持字符串、数字、颜色等类型。
变量插值变量可用于选择器和属性名,如 .{name} 会动态拼接变量 name 的值作为类名。
嵌套规则支持 CSS 规则嵌套,简化层级关系书写,如 nav { ul { margin: 0 } } 编译成 nav ul { margin: 0 }
混入(Mixin)通过函数定义可复用的样式块,如 border-radius(n) 定义并调用 border-radius(5px)。支持参数和默认值。
运算支持数学运算,如 width = 100px / 2,也支持字符串连接和颜色运算。
条件语句支持 if 语句控制样式生成,如 if isPrimary then color = red else color = blue
循环支持 foreach 循环迭代生成样式,如 for i in 1..3 生成多个类。
函数支持自定义函数,封装复杂逻辑返回值,增强样式的动态能力。
引入(Import)支持引入其他 Stylus 文件或 CSS 文件,如 @import 'variables.styl'
颜色函数内置丰富颜色处理函数,如 lighten(), darken(), saturate() 等,方便颜色调整。

有用过 PostCSS 吗?

答案

PostCSS 是 CSS 的处理器,可以类比为 Babel 对 JavaScript 的处理。通过插件机制实现对 CSS 的转换和增强。常见的插件包括

  • autoprefixer:自动添加浏览器前缀,兼容性处理。
  • cssnano:CSS 压缩和优化。
  • postcss-preset-env:允许使用未来的 CSS 特性,自动转换为当前浏览器支持的语法。
  • postcss-import:支持 CSS 文件的导入,类似于 Sass 的 @import
  • postcss-nested:支持嵌套规则,类似于 Sass 的嵌套语法。

参考 PostCSS Plugin 一个简单的 PostCSS 插件示例

module.exports = (opts = {}) => {
return {
postcssPlugin: 'postcss-example',
Once (root, { result }) {
root.walkDecls(decl => {
if (decl.prop === 'example') {
decl.cloneBefore({ prop: 'color', value: 'red' })
decl.remove()
}
})
}
}
}
module.exports.postcss = true

通过如下方式消费插件

const postcss = require('postcss')
const example = require('postcss-example')
postcss([example])
.process(css, { from: undefined })
.then(result => {
console.log(result.css)
})

如何优化CSS性能?

答案

核心概念

CSS性能优化涉及选择器优化、渲染性能、文件大小等多个方面。

选择器优化

  1. 避免过度嵌套

    /* 差:过度嵌套 */
    .container .wrapper .content .item .link { color: blue; }

    /* 好:直接选择 */
    .link { color: blue; }
  2. 使用高效的选择器

    /* 选择器性能排序(从快到慢) */
    #id { } /* 最快 */
    .class { } /* 很快 */
    element { } /* 快 */
    [attribute] { } /* 中等 */
    :pseudo-class { } /* 中等 */
    element element { } /* 较慢 */

渲染性能优化

  1. 使用transform和opacity

    /* 差:触发重排 */
    .animate {
    left: 100px;
    top: 100px;
    }

    /* 好:只触发重绘 */
    .animate {
    transform: translate(100px, 100px);
    }
  2. 避免强制同步布局

    // 差:强制同步布局
    const width = element.offsetWidth
    element.style.width = width + 100 + 'px'

    // 好:使用requestAnimationFrame
    requestAnimationFrame(() => {
    element.style.width = element.offsetWidth + 100 + 'px'
    })

文件大小优化

  1. 压缩CSS

    /* 压缩前 */
    .container {
    margin: 10px;
    padding: 20px;
    background-color: #ffffff;
    }

    /* 压缩后 */
    .container{margin:10px;padding:20px;background-color:#fff}
  2. 移除未使用的CSS

    /* 使用PurgeCSS等工具移除未使用的样式 */
    /* 只保留实际使用的样式 */

实际应用

/* 性能优化的CSS示例 */
/* 使用CSS变量减少重复 */
:root {
--primary-color: #007bff;
--border-radius: 4px;
}

/* 高效的选择器 */
.button {
background: var(--primary-color);
border-radius: var(--border-radius);
}

/* 使用will-change优化动画 */
.optimized-animation {
will-change: transform;
transition: transform 0.3s ease;
}

面试官视角

  • :不了解性能优化,使用低效的CSS
  • :知道基本优化方法,能避免明显的性能问题
  • :深入理解性能机制,能系统性地优化CSS

延伸阅读

CSS动画性能如何优化?

答案

核心概念

CSS动画性能直接影响用户体验,优化动画可以提升页面流畅度和响应性。

性能优化策略

  1. 使用transform和opacity

    /* 差:改变布局属性 */
    .animate {
    left: 100px;
    top: 100px;
    }

    /* 好:使用transform */
    .animate {
    transform: translate(100px, 100px);
    }
  2. 避免触发重排和重绘

    /* 差:触发重排 */
    .animate {
    width: 200px;
    height: 200px;
    margin: 10px;
    }

    /* 好:只改变transform */
    .animate {
    transform: scale(1.2);
    }
  3. 使用will-change属性

    .optimized {
    will-change: transform;
    transition: transform 0.3s ease;
    }
  4. 合理使用GPU加速

    .gpu-accelerated {
    transform: translateZ(0); /* 强制GPU加速 */
    }

实际应用

/* 高性能动画示例 */
.slide-in {
transform: translateX(-100%);
transition: transform 0.3s ease;
will-change: transform;
}

.slide-in.active {
transform: translateX(0);
}

/* 避免性能问题的动画 */
.fade-in {
opacity: 0;
transition: opacity 0.3s ease;
}

.fade-in.visible {
opacity: 1;
}

面试官视角

  • :不了解动画性能问题,使用会触发重排的属性
  • :知道使用transform和opacity,了解基本优化方法
  • :深入理解渲染机制,能系统性地优化动画性能

延伸阅读

重置 css 和标准化 css 的区别?你会选择哪种?为什么?

答案
  • 重置是为了统一不同浏览器器的默认样式,需要重新定制所有元素的基础表现
  • 标准化是部分保留默认样式,并修复不同浏览器的显示差异 典型应用例如 normalize css

延伸阅读