Less CSS 预处理:动态样式表语言
Less CSS 预处理:动态样式表语言
Less 是一门 CSS 预处理语言,它在 CSS 的语法基础之上,引入了变量、混合、运算、函数等动态特性,让样式表的编写更加高效、可维护。通过 Less 编译器,最终生成的依然是标准的 CSS 文件,因此浏览器无需任何特殊支持即可正常解析。
与原生 CSS 相比,Less 就像是为样式赋予了编程思维。你可以在一个地方定义颜色、字体,然后在任意位置复用它们;可以通过嵌套直观地反映 HTML 层级结构;还可以封装一组样式并在不同选择器中按需调用。这些能力大幅减少了代码冗余,让修改和扩展都变得更加安全、快捷。
快速上手:从安装到编译
Less 的编译可以在多种环境下执行,你无需掌握复杂的构建工具即可立即开始使用。
在浏览器端体验(开发阶段)
最简单的方式是通过 JS 直接在浏览器中解析 Less 文件。在 HTML 中引入 .less 文件,并在其之前加载 Less.js。
<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="https://cdn.jsdelivr.net/npm/less" ></script>
注意: 这种方式不适合生产环境,每次页面加载都会实时编译,影响性能。建议仅在本地快速试验时使用。
命令行工具(推荐)
通过 Node.js 的 npm 全局安装 Less 编译器,之后可以在终端中将 .less 文件编译为 .css。
npm install -g less
lessc styles.less styles.css
lessc 命令支持多种选项,例如压缩输出:
lessc --clean-css styles.less styles.min.css
与构建工具集成
实际项目通常配合 Webpack、Gulp、Vite 等工具使用。以 Webpack 为例,配置 less-loader 后,每次保存文件即可自动编译。Vue 单文件组件中,直接在 <style lang="less"> 内编写 Less,由 vue-loader 自动处理。
变量:一次定义,全局复用
变量是 Less 最基础也最强大的特性。你可以把颜色、字体系列、尺寸值等定义为变量,在任意地方引用。一旦需要修改主题色,只需更改变量的值,所有引用处都会同步生效。
// 定义变量
@primary-color: #3b82f6;
@border-radius: 8px;
@base-font: 'Helvetica Neue', sans-serif;
// 使用变量
.button {
background-color: @primary-color;
border-radius: @border-radius;
font-family: @base-font;
}
变量插值:变量还可以用在选择器名称、属性名、URL 中,使用 @{} 包裹。
@selector: banner;
@image-path: "../images";
.@{selector} {
background: url("@{image-path}/bg.png");
}
作用域与延迟加载:Less 变量遵循块级作用域,但表现类似“延迟加载”——在同一个作用域内,变量可以预先使用,后面才定义,最终取值以最后定义的为准。这一特性让变量可被覆盖,十分灵活。
@color: red;
.box {
color: @color; // 最后会是 blue
@color: blue;
}
混合:封装可复用的样式块
混合(Mixin)让你把一组样式规则当作函数一样,在其他规则集中“调用”。混合可以携带参数,具备默认值,甚至支持内容条件判断。
无参数混合
定义一个普通的类选择器,当它在另一个规则集中被引用时,它的所有属性都会被复制过来。
// 定义混合
.rounded-corners {
border-radius: 6px;
-webkit-border-radius: 6px;
}
// 使用混合
.card {
.rounded-corners();
background: #fff;
}
如果混合不希望输出到 CSS(作为纯粹的工具类),可以在其名称后加上 (),这样编译时不会生成对应的选择器。
.clearfix() {
&:after {
content: "";
display: table;
clear: both;
}
}
.container {
.clearfix();
}
带参数的混合
参数混合可以接收传入的值,动态生成样式,就像函数一样。
.shadow(@x: 0, @y: 2px, @blur: 4px, @color: rgba(0,0,0,.2)) {
box-shadow: @x @y @blur @color;
}
.modal {
.shadow(0, 4px, 8px, rgba(0,0,0,.3));
}
@arguments 变量
在混合内部,@arguments 代表所有传入的参数,可以一次性赋值给属性。
.box-shadow(@args) {
-webkit-box-shadow: @arguments;
box-shadow: @arguments;
}
.element {
.box-shadow(2px 2px 5px #999);
}
模式匹配与守卫
通过给混合名称设置不同的参数签名,可以根据参数个数或类型进行匹配。结合 when 关键字,还能实现条件判断。
// 根据亮度设置文字颜色
.text-color(@bg) when (lightness(@bg) >= 50%) {
color: #333;
}
.text-color(@bg) when (lightness(@bg) < 50%) {
color: #fff;
}
.header {
background: #444;
.text-color(#444);
}
嵌套:反映 HTML 结构,减少重复
Less 允许将子选择器写在父选择器内部,自动生成后代、父子组合选择器。配合 & 符号,可以精确控制伪类、伪元素或与父级拼接的选择器。
.nav {
background: #222;
ul {
margin: 0;
padding: 0;
li {
display: inline-block;
a {
color: white;
&:hover {
color: #3b82f6;
}
}
}
}
&-fixed {
position: fixed;
top: 0;
}
}
编译后的 CSS:
.nav { background: #222; }
.nav ul { margin: 0; padding: 0; }
.nav ul li { display: inline-block; }
.nav ul li a { color: white; }
.nav ul li a:hover { color: #3b82f6; }
.nav-fixed { position: fixed; top: 0; }
合理使用嵌套能让样式表的结构更接近 HTML,但过深的嵌套会产生冗余的选择器,一般建议不超过 3 层。
运算与函数:让数值动态计算
Less 支持数值之间的加减乘除运算,并且会自动处理单位转换。配合内置的颜色、数学、字符串函数,能实现复杂的动态样式。
基础运算
@base: 16px;
@padding: @base * 1.5;
.sidebar {
width: 100% / 3 + 20px;
padding: @padding;
line-height: @base * 2;
}
颜色也可以参与运算,Less 会在通道级别进行加减。
@color: #4488cc;
.box {
background: @color + #111; // 每个通道加 0x11
border-color: @color - #222;
}
常用内置函数
- 颜色处理:
lighten(),darken(),fade(),saturate(),mix() - 数学:
ceil(),floor(),round(),percentage() - 字符串:
escape(),replace() - 列表:
length(),extract()
@primary: #3b82f6;
.btn {
background: @primary;
&:hover {
background: lighten(@primary, 10%);
}
&:active {
background: darken(@primary, 10%);
}
}
继承:精简生成的 CSS
与混合复制属性不同,继承(extend)会在编译时将多个选择器分组,共享相同的属性集合,从而减少重复代码。
.message {
padding: 10px;
border: 1px solid #ddd;
}
.success {
&:extend(.message);
border-color: green;
}
.error {
&:extend(.message);
border-color: red;
}
编译后:
.message,
.success,
.error {
padding: 10px;
border: 1px solid #ddd;
}
.success { border-color: green; }
.error { border-color: red; }
extend 相比混合不会产生多个副本,更适合那些需要严格精简 CSS 体积的场景。但要注意,它无法像带参数的混合那样传递变量。
导入与模块化
当项目样式变得庞大,可以将代码拆分为多个 Less 文件。使用 @import 可以引入其他模块,并且支持将导入文件合并为单一 CSS 输出,减少 HTTP 请求。
// variables.less
@brand-color: #e11d48;
// mixins.less
.rounded(@radius: 4px) {
border-radius: @radius;
}
// main.less
@import "variables";
@import "mixins";
.header {
color: @brand-color;
.rounded(8px);
}
如果希望被导入的文件只在编译时使用而不输出 CSS,可以将其命名为 _file.less 或使用 (reference) 选项导入。
@import (reference) "my-mixins";
命名空间与访问器
当多个混合放在一个模块中,为了避免名称冲突或按功能分组,可以使用命名空间。通过 #namespace > .mixin 的方式来引用。
#utils {
.center() {
margin-left: auto;
margin-right: auto;
}
.hide() {
display: none;
}
}
.container {
#utils > .center();
}
循环与递归生成样式
Less 虽然没有传统的循环语句,但可以利用递归混合配合守卫条件来生成重复的规则,例如生成一套网格类。
.generate-columns(@n, @i: 1) when (@i =< @n) {
.col-@{i} {
width: (@i * 100% / @n);
}
.generate-columns(@n, @i + 1);
}
.generate-columns(12);
上面的代码将生成 .col-1 到 .col-12 并自动计算宽度。
总结与最佳实践
- 优先使用变量:将颜色、字号、间距等可复用的设计标记定义为变量,构建主题系统。
- 混合优于复制:将重复的样式片段抽象为参数化混合,避免代码冗余。
- 合理嵌套:通过嵌套映射 DOM 层级,但避免超过 3 层深度。
- 需要精简时使用继承:当多个选择器共享完全相同的属性集时,用
extend代替混合,可优化输出体积。 - 模块化拆分:将全局变量、混合、基础样式、组件样式分别存放在不同文件,通过
@import组织。 - 保持兼容性:利用 Autoprefixer 等工具与 Less 配合,自动添加浏览器前缀;避免使用现代 CSS 尚未广泛支持的属性作为运算对象。
Less 作为动态样式表语言,并不会增加项目复杂度,反而能通过清晰的工程化手段让 CSS 更易于维护。现在,你可以将现有的 CSS 文件直接改名为 .less 开始尝试,逐步引入上述特性,感受预处理器带来的效率提升。