学习Less,看这篇就够了(从入门到实战)
Less(Leaner Style Sheets)是CSS预处理器,在原生CSS基础上增加变量、嵌套、混合、函数、运算、模块化等编程特性,让CSS更易维护、复用、扩展,最终编译成标准CSS运行。本文从环境搭建、核心语法、进阶技巧、实战规范全流程覆盖,新增多个优雅使用案例(含Less源码与编译后CSS对比),直接上手可用。
一、Less基础:是什么、为什么、怎么用
1.1 核心优势(为什么用Less)
- 变量统一管理:颜色、尺寸、字体等全局配置,一改全改
- 嵌套结构:完全匹配HTML层级,代码更直观、减少重复选择器
- 混合(Mixin):复用样式片段,像函数一样传参
- 运算/函数:支持加减乘除、颜色明暗、单位转换
- 模块化:拆分文件、导入合并,便于团队协作与维护
- 兼容原生CSS:所有CSS代码可直接写在Less中,零学习门槛
1.2 环境搭建(3种方式,最快1分钟)
方式1:浏览器直接运行(学习/原型)
<!-- 1. 引入Less文件,rel必须是stylesheet/less -->
<link rel="stylesheet/less" type="text/css" href="styles.less" />
<!-- 2. 引入Less编译器(CDN,已替换为可用链接) -->
<script src="https://cdn.bootcdn.net/ajax/libs/less.js/4.2.0/less.min.js"></script>
⚠️ 仅适合开发调试,生产环境禁止使用(性能差、依赖JS);原CDN链接报错“link dead”,已替换为稳定可用版本
方式2:VSCode自动编译(推荐,日常开发)
- 安装插件:Easy LESS
- 新建
.less文件,保存时自动生成同名.css - 配置(可选,settings.json):
"less.compile": {
"out": "../css/", // 输出到css文件夹
"compress": true, // 压缩CSS
"sourceMap": false
}
方式3:命令行编译(项目构建)
- 安装Node.js,全局安装Less:
npm install -g less
lessc -v # 验证安装
- 编译命令:
lessc styles.less styles.css # 基础编译
lessc styles.less styles.min.css --compress # 压缩输出
二、Less核心语法(必掌握,直接套用)
2.1 变量(@变量名:值)—— 统一管理,一改全改
变量以@开头,可存颜色、尺寸、字体、路径等,支持插值(选择器、属性、URL)。
// 1. 基础变量定义(语义化命名,便于维护)
@primary: #2563eb; // 主色
@success: #16a34a; // 成功色
@font-size: 16px; // 基础字体
@spacing: 20px; // 基础间距
@img-path: "../images"; // 图片路径
// 2. 变量使用(结合运算,减少硬编码)
.btn {
background: @primary;
font-size: @font-size;
padding: @spacing/2; // 10px,无需手动计算
margin: @spacing;
}
// 3. 变量插值(复用选择器、属性、URL,避免重复书写)
@selector: card;
@prop: width;
.@{selector} { // 编译为 .card
@{prop}: 300px; // 编译为 width:300px
background: url("@{img-path}/bg.png");
}
编译后CSS:
.btn {
background: #2563eb;
font-size: 16px;
padding: 10px;
margin: 20px;
}
.card {
width: 300px;
background: url("../images/bg.png");
}
优雅要点:变量语义化命名,通过插值复用选择器和路径,运算替代硬编码,后续修改主色、间距时,仅需修改变量值,无需逐行修改样式。
2.2 嵌套规则(&父选择器)—— 匹配HTML结构,告别重复
Less允许选择器嵌套,&代表当前父选择器,用于伪类、交集选择器、兄弟选择器,避免重复书写父选择器。
// HTML结构:<div class="header"><nav class="nav"><a href="#" class="active">首页</a></nav></div>
.header {
width: 100%;
height: 60px;
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.1); // 增加阴影,提升质感
.nav {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
a {
color: #333;
text-decoration: none;
padding: 0 @spacing/2; // 复用间距变量
margin: 0 @spacing;
// & 代表父选择器 .nav a,避免书写 .nav a:hover
&:hover {
color: @primary;
transition: color 0.3s ease; // 过渡效果,更优雅
}
&.active {
font-weight: bold;
color: @primary;
border-bottom: 2px solid @primary;
}
}
}
}
编译后CSS(对比:选择器自动拼接,无需手动重复):
.header {
width: 100%;
height: 60px;
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.header .nav {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.header .nav a {
color: #333;
text-decoration: none;
padding: 0 10px;
margin: 0 20px;
}
.header .nav a:hover {
color: #2563eb;
transition: color 0.3s ease;
}
.header .nav a.active {
font-weight: bold;
color: #2563eb;
border-bottom: 2px solid #2563eb;
}
优雅要点:嵌套结构与HTML完全对应,可读性极强;&的使用避免重复书写父选择器(如.header .nav a),同时结合过渡效果,提升交互质感。
2.3 混合(Mixin)—— 复用样式,支持传参(核心)
Mixin是可复用的样式片段,带()不输出到CSS,不带()会输出;支持参数、默认值、条件判断,可封装公共样式,避免重复编码。
(1)基础Mixin(无参)—— 封装公共样式
// 定义:清除浮动(公共Mixin,可全局调用)
.clearfix() {
&::after {
content: "";
display: block;
clear: both;
height: 0;
visibility: hidden;
}
}
// 定义:居中布局(公共Mixin,复用性强)
.center() {
display: flex;
justify-content: center;
align-items: center;
}
// 使用:多个容器复用,无需重复书写样式
.container {
.clearfix(); // 调用清除浮动
width: 1200px;
margin: 0 auto;
}
.modal {
.center(); // 调用居中布局
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
}
编译后CSS(对比:Mixin样式自动注入,无需重复书写):
.container {
width: 1200px;
margin: 0 auto;
}
.container::after {
content: "";
display: block;
clear: both;
height: 0;
visibility: hidden;
}
.modal {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
}
(2)带参数Mixin(默认值、多参数)—— 动态生成样式
// 定义:按钮样式(带参数+默认值,灵活适配不同场景)
.btn(@bg: @primary, @color: #fff, @radius: 4px, @padding: 8px 16px) {
display: inline-block;
padding: @padding;
background: @bg;
color: @color;
border-radius: @radius;
cursor: pointer;
border: none;
outline: none;
transition: all 0.3s ease; // 统一过渡效果
&:hover {
filter: brightness(0.9); // hover变暗,无需单独写样式
transform: translateY(-2px); // 轻微上浮,提升交互
}
&:active {
transform: translateY(0);
}
}
// 使用:按需传参,无需重复书写按钮基础样式
.btn-primary { .btn(); } // 使用默认值(主色按钮)
.btn-success { .btn(@success); } // 传单个参数(成功色按钮)
.btn-round { .btn(@primary, #fff, 50%, 10px 20px); } // 传全部参数(圆形按钮)
.btn-small { .btn(@primary, #fff, 4px, 4px 8px); } // 传部分参数(小尺寸按钮)
编译后CSS(对比:自动生成不同样式的按钮,代码简洁):
.btn-primary {
display: inline-block;
padding: 8px 16px;
background: #2563eb;
color: #fff;
border-radius: 4px;
cursor: pointer;
border: none;
outline: none;
transition: all 0.3s ease;
}
.btn-primary:hover {
filter: brightness(0.9);
transform: translateY(-2px);
}
.btn-primary:active {
transform: translateY(0);
}
.btn-success {
display: inline-block;
padding: 8px 16px;
background: #16a34a;
color: #fff;
border-radius: 4px;
cursor: pointer;
border: none;
outline: none;
transition: all 0.3s ease;
}
.btn-success:hover {
filter: brightness(0.9);
transform: translateY(-2px);
}
.btn-success:active {
transform: translateY(0);
}
.btn-round {
display: inline-block;
padding: 10px 20px;
background: #2563eb;
color: #fff;
border-radius: 50%;
cursor: pointer;
border: none;
outline: none;
transition: all 0.3s ease;
}
.btn-round:hover {
filter: brightness(0.9);
transform: translateY(-2px);
}
.btn-round:active {
transform: translateY(0);
}
.btn-small {
display: inline-block;
padding: 4px 8px;
background: #2563eb;
color: #fff;
border-radius: 4px;
cursor: pointer;
border: none;
outline: none;
transition: all 0.3s ease;
}
.btn-small:hover {
filter: brightness(0.9);
transform: translateY(-2px);
}
.btn-small:active {
transform: translateY(0);
}
(3)命名空间(组织Mixin,避免冲突)
// 命名空间:统一管理公共Mixin,避免与业务样式冲突
#utils() { // 带(),不输出到CSS
.clearfix() {
&::after {
content: "";
display: block;
clear: both;
height: 0;
visibility: hidden;
}
}
.center() {
display: flex;
justify-content: center;
align-items: center;
}
.shadow() { // 新增阴影Mixin
box-shadow: 0 2px 12px rgba(0,0,0,0.1);
}
}
// 调用:通过命名空间调用,清晰区分公共样式与业务样式
.box {
#utils.center();
#utils.shadow();
width: 300px;
height: 200px;
background: #fff;
}
编译后CSS:
.box {
display: flex;
justify-content: center;
align-items: center;
box-shadow: 0 2px 12px rgba(0,0,0,0.1);
width: 300px;
height: 200px;
background: #fff;
}
2.4 运算(+ - * /)—— 自动计算,减少手动计算
支持颜色、数值、单位运算,Less自动处理单位(优先左侧单位),避免手动计算错误,代码更优雅。
@base: 20px;
@width: 1000px;
@card-width: @width / 5; // 200px,自动计算栅格宽度
@light-primary: lighten(@primary, 10%); // 主色变亮10%,无需手动计算色值
.box {
width: @width - 40px; // 960px,自适应宽度
padding: @base * 1.5; // 30px,间距按比例调整
margin: (@base / 2); // 10px,统一间距
}
.card {
width: @card-width;
background: @light-primary;
margin: @base;
}
⚠️ 除法建议加括号:(100px / 2),避免与CSS语法冲突
编译后CSS(对比:自动计算数值和颜色,无需手动计算):
.box {
width: 960px;
padding: 30px;
margin: 10px;
}
.card {
width: 200px;
background: #3b82f6; // 自动计算的亮主色
margin: 20px;
}
2.5 内置函数—— 颜色、字符串、数学处理(常用)
Less提供大量内置函数,无需定义直接用,提升效率,让样式更优雅。
// 颜色函数(最常用,自动处理色值)
@primary: #2563eb;
@dark-primary: darken(@primary, 10%); // 主色变暗10%
@fade-primary: fade(@primary, 50%); // 主色半透明
@saturate-primary: saturate(@primary, 20%); // 主色增加饱和度
// 数学函数(自动处理数值)
@base-font: 16px;
@title-font: ceil(@base-font * 1.5); // 24px,向上取整
@sub-font: floor(@base-font * 0.8); // 12px,向下取整
// 使用:结合函数和变量,样式更灵活
.title {
font-size: @title-font;
color: @dark-primary;
}
.sub-title {
font-size: @sub-font;
color: @fade-primary;
}
.btn {
background: @saturate-primary;
&:hover {
background: @dark-primary;
}
}
编译后CSS:
.title {
font-size: 24px;
color: #1d4ed8; // 变暗后的主色
}
.sub-title {
font-size: 12px;
color: rgba(37, 99, 235, 0.5); // 半透明主色
}
.btn {
background: #1d4ed8; // 增加饱和度后的主色
}
.btn:hover {
background: #1d4ed8;
}
2.6 导入(@import)—— 模块化拆分,代码解耦
拆分变量、Mixin、公共样式,通过@import合并,支持省略.less后缀,让代码结构更清晰,便于维护。
// 1. 拆分文件(按功能拆分,各司其职)
// variables.less → 全局变量(单独管理,一改全改)
@primary: #2563eb;
@font-size: 16px;
@spacing: 20px;
// mixins.less → 公共混合(单独管理,全局复用)
.clearfix() { ... }
.btn(@bg: @primary) { ... }
.center() { ... }
// base.less → 基础样式(reset、全局样式)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Microsoft YaHei", sans-serif;
font-size: @font-size;
color: #333;
}
// 2. 主文件导入(统一入口,结构清晰)
@import "variables"; // 省略.less
@import "mixins";
@import "base";
// 编写业务样式(仅关注业务,无需关注公共样式)
.header {
.clearfix();
height: 60px;
.nav {
.center();
a {
color: #333;
&:hover { color: @primary; }
}
}
}
⚠️ @import (reference) "mixins.less"; → 仅导入Mixin,不输出到CSS
编译后CSS(对比:所有导入的样式自动合并,结构清晰):
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Microsoft YaHei", sans-serif;
font-size: 16px;
color: #333;
}
.header {
height: 60px;
}
.header::after {
content: "";
display: block;
clear: both;
height: 0;
visibility: hidden;
}
.header .nav {
display: flex;
justify-content: center;
align-items: center;
}
.header .nav a {
color: #333;
}
.header .nav a:hover {
color: #2563eb;
}
2.7 作用域与注释
- 作用域:就近原则,局部变量覆盖全局变量,类似JS,可灵活控制变量作用范围
// 全局变量(整个项目可用)
@color: red;
// 局部变量(仅在.box内可用,不影响全局)
.box {
@color: blue;
color: @color; // blue(局部优先)
}
// 其他模块仍使用全局变量
.text {
color: @color; // red
}
编译后CSS:
.box {
color: blue;
}
.text {
color: red;
}
-
注释:
- 单行注释:
// 注释→ 编译后不保留(用于开发备注,不污染生产CSS) - 多行注释:
/* 注释 */→ 编译后保留(用于生产环境备注,如版权信息)
- 单行注释:
三、Less进阶技巧(提升效率,避坑)
3.1 父选择器&高级用法
// 1. 前缀拼接(批量生成同类样式,避免重复)
.btn {
display: inline-block;
padding: 8px 16px;
border-radius: 4px;
&-primary { background: @primary; color: #fff; } // .btn-primary
&-success { background: @success; color: #fff; } // .btn-success
&-warning { background: #f59e0b; color: #fff; } // .btn-warning
&-disabled { background: #ccc; color: #666; cursor: not-allowed; } // .btn-disabled
}
// 2. 多层嵌套&(精准定位子元素,避免冗长选择器)
.list {
width: 100%;
&-item {
padding: @spacing;
border-bottom: 1px solid #eee;
&:last-child { border-bottom: none; } // .list-item:last-child
&-title { font-weight: bold; color: #333; } // .list-item-title
&-content { color: #666; margin-top: 8px; } // .list-item-content
}
}
编译后CSS(对比:自动拼接选择器,批量生成样式,代码简洁):
.btn {
display: inline-block;
padding: 8px 16px;
border-radius: 4px;
}
.btn-primary {
background: #2563eb;
color: #fff;
}
.btn-success {
background: #16a34a;
color: #fff;
}
.btn-warning {
background: #f59e0b;
color: #fff;
}
.btn-disabled {
background: #ccc;
color: #666;
cursor: not-allowed;
}
.list {
width: 100%;
}
.list-item {
padding: 20px;
border-bottom: 1px solid #eee;
}
.list-item:last-child {
border-bottom: none;
}
.list-item-title {
font-weight: bold;
color: #333;
}
.list-item-content {
color: #666;
margin-top: 8px;
}
3.2 条件Mixin(when)—— 动态生成样式
// 定义:根据尺寸生成不同按钮(条件判断,灵活适配)
.btn(@size) when (@size = large) {
padding: 12px 24px;
font-size: 18px;
border-radius: 6px;
}
.btn(@size) when (@size = small) {
padding: 4px 8px;
font-size: 14px;
border-radius: 3px;
}
// 新增条件:根据主题生成不同颜色
.btn(@size, @theme) when (@theme = dark) {
.btn(@size);
background: #333;
color: #fff;
}
// 使用:按需传入条件,自动生成对应样式
.btn-lg { .btn(large); } // 大尺寸按钮
.btn-sm { .btn(small); } // 小尺寸按钮
.btn-lg-dark { .btn(large, dark); } // 大尺寸深色按钮
编译后CSS:
.btn-lg {
padding: 12px 24px;
font-size: 18px;
border-radius: 6px;
}
.btn-sm {
padding: 4px 8px;
font-size: 14px;
border-radius: 3px;
}
.btn-lg-dark {
padding: 12px 24px;
font-size: 18px;
border-radius: 6px;
background: #333;
color: #fff;
}
3.3 循环(for)—— 批量生成样式(Less 3.9+)
// 生成1-5列栅格(循环遍历,无需手动写5个样式)
.generate-columns(@n, @i: 1) when (@i =< @n) {
.col-@{i} {
width: (@i * 100% / @n);
float: left;
padding: @spacing/2;
box-sizing: border-box;
}
.generate-columns(@n, @i + 1); // 递归循环
}
.generate-columns(5); // 生成col-1到col-5
// 生成不同尺寸的margin样式(批量生成,复用性强)
.generate-margin(@n, @i: 1) when (@i =< @n) {
.mt-@{i} { margin-top: @i * 8px; }
.mb-@{i} { margin-bottom: @i * 8px; }
.generate-margin(@n, @i + 1);
}
.generate-margin(5); // 生成mt-1~mt-5、mb-1~mb-5
编译后CSS(对比:自动生成10个margin样式+5个栅格样式,无需手动书写):
.col-1 {
width: 20%;
float: left;
padding: 10px;
box-sizing: border-box;
}
.col-2 {
width: 40%;
float: left;
padding: 10px;
box-sizing: border-box;
}
.col-3 {
width: 60%;
float: left;
padding: 10px;
box-sizing: border-box;
}
.col-4 {
width: 80%;
float: left;
padding: 10px;
box-sizing: border-box;
}
.col-5 {
width: 100%;
float: left;
padding: 10px;
box-sizing: border-box;
}
.mt-1 { margin-top: 8px; }
.mb-1 { margin-bottom: 8px; }
.mt-2 { margin-top: 16px; }
.mb-2 { margin-bottom: 16px; }
.mt-3 { margin-top: 24px; }
.mb-3 { margin-bottom: 24px; }
.mt-4 { margin-top: 32px; }
.mb-4 { margin-bottom: 32px; }
.mt-5 { margin-top: 40px; }
.mb-5 { margin-bottom: 40px; }
3.4 映射(Maps)—— 像对象一样取值(Less 3.5+)
// 定义颜色映射(类似JS对象,统一管理所有颜色,便于查找和修改)
@colors: {
primary: #2563eb;
success: #16a34a;
warning: #f59e0b;
danger: #ef4444;
dark: #333;
light: #f5f5f5;
};
// 定义尺寸映射(统一管理尺寸,避免硬编码)
@sizes: {
small: 14px;
base: 16px;
large: 18px;
xlarge: 24px;
};
// 使用:通过映射取值,代码更简洁,维护更方便
.btn {
font-size: @sizes[base];
&-primary { background: @colors[primary]; }
&-success { background: @colors[success]; }
&-warning { background: @colors[warning]; }
}
.title {
font-size: @sizes[xlarge];
color: @colors[dark];
}
编译后CSS:
.btn {
font-size: 16px;
}
.btn-primary {
background: #2563eb;
}
.btn-success {
background: #16a34a;
}
.btn-warning {
background: #f59e0b;
}
.title {
font-size: 24px;
color: #333;
}
四、实战规范与常见问题(避坑指南)
4.1 项目规范(推荐)
- 文件结构:
src/
├── less/
│ ├── variables.less # 全局变量(颜色、尺寸、字体)
│ ├── mixins.less # 公共混合(清除浮动、按钮、居中)
│ ├── base.less # 基础样式(reset、全局)
│ ├── components/ # 组件(按钮、卡片、导航)
│ └── main.less # 主入口(导入所有)
- 命名:变量用
@xxx-xxx(@primary-color),Mixin用小驼峰/短横线,语义化
4.2 常见问题与解决
- 嵌套过深:最多3层,避免编译后选择器过长、性能差
- 变量污染:全局变量放单独文件,局部变量仅在模块内使用
- 编译报错:检查括号、分号、变量定义,优先用Easy LESS实时提示
- 单位冲突:运算时统一单位,或用
unit()函数转换
五、Less vs Sass(快速对比,选择更合适)
| 特性 | Less | Sass |
|---|---|---|
| 变量符号 | @ | $ |
| 编译环境 | Node.js/浏览器 | Ruby/Node.js |
| 语法 | 接近CSS,易上手 | 缩进/花括号两种 |
| 循环/条件 | 支持(Less 3.9+) | 原生支持,更强大 |
| 生态 | 轻量,适合中小型项目 | 功能全,适合大型项目 |
六、总结与下一步
Less核心就是把CSS变成可维护的代码:变量统一、嵌套清晰、Mixin复用、函数简化、模块化拆分。新增的优雅案例均贴合实际开发,通过Less源码与编译后CSS对比,可清晰看到Less如何简化编码、提升效率。