Article
第1章:初识 Less
1.1 什么是 Less
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| Less 定义 | .less 文件扩展名 | 一种 CSS 预处理器语言,扩展了 CSS 功能,支持变量、嵌套、混合等特性 | // 这是一个 Less 文件@primary-color: #4285f4;body { color: @primary-color;} | Less 不是标准 CSS,需编译为 CSS 才能被浏览器识别 |
| 预处理器概念 | — | 将高级语法转换为浏览器可执行的 CSS 代码 | — | 理解”预处理”是编译前的开发阶段,不直接运行于浏览器 |
1.2 Less 与 CSS 的关系
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 语法兼容性 | 所有合法 CSS 均为合法 Less | Less 是 CSS 的超集,可直接写 CSS 代码 | p { font-size: 16px;} | 可在 .less 文件中直接使用 CSS 规则,无需修改 |
| 编译输出 | lessc input.less output.css | 将 Less 转换为标准 CSS | 输入:@color: red; p { color: @color; }输出: p { color: red; } | 最终部署的是编译后的 .css 文件,而非 .less |
| 层级关系 | — | Less → 编译 → CSS → 浏览器渲染 | — | 开发用 Less,生产用 CSS |
1.3 Less 的优势与应用场景
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 变量复用 | @variable-name: value; | 统一管理颜色、字体、间距等样式常量 | @theme-color: #007bff;.btn { background: @theme-color; } | 提升维护性,避免重复值 |
| 结构嵌套 | 选择器内部写子规则 | 模拟 HTML 结构,提升可读性 | .nav { ul { margin: 0; } li { display: inline; }} | 避免过度嵌套导致选择器过深 |
| 混合(Mixin) | .mixin-name { ... } | 复用样式块,支持参数化 | .rounded(@r: 4px) { border-radius: @r;}.box { .rounded(8px); } | 减少重复代码,提升组件化能力 |
| 函数与运算 | lighten(@color, 10%) | 动态生成颜色、尺寸等 | @base: #000;p { color: lighten(@base, 50%); } | 支持颜色、数值运算,增强灵活性 |
| 应用场景 | — | 主题定制、大型项目、组件库开发 | 使用变量实现深色/浅色主题切换 | 特别适合需要高可维护性和一致性的项目 |
1.4 开发环境搭建(编译器、工具)
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| Node.js 安装 | npm install -g less | 全局安装 Less 编译器 | 在终端运行:npm install -g less | 需先安装 Node.js 和 npm |
| 编译命令 | lessc input.less output.css | 手动将 Less 文件编译为 CSS | lessc styles.less styles.css | 可添加 --watch 参数监听文件变化 |
| VS Code 插件 | Easy LESS / Live Server | 实时编译与预览 | 安装插件后保存 .less 文件自动输出 .css | 配置插件选项以指定输出路径 |
| Webpack 集成 | less-loader | 在构建流程中自动处理 Less | module: { rules: [ { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] } ]} | 需配合 css-loader、style-loader 使用 |
| 浏览器端编译 | <script src="less.js"></script> | 直接在浏览器中编译(仅开发调试) | 引入 less.js 后加载 .less 文件 | 性能差,禁止用于生产环境 |
第2章:变量(Variables)
2.1 变量的定义与使用
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 变量声明 | @variable-name: value; | 定义可复用的值,如颜色、尺寸、字体等 | @primary-color: #007bff;@font-size: 16px; | 变量名以 @ 开头,区分大小写 |
| 变量引用 | property: @variable-name; | 在样式规则中使用已定义的变量 | .btn { background-color: @primary-color; font-size: @font-size;} | 变量可在任意属性值位置使用 |
| 变量命名规范 | @theme-bg, @spacing-lg | 提高可读性和维护性 | @text-color-dark: #333;@border-radius-base: 4px; | 推荐使用连字符命名,避免特殊字符 |
2.2 变量作用域
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 局部作用域 | 在规则块内定义变量 | 限制变量仅在当前块及其嵌套中有效 | .scope-a { @color: red; p { color: @color; }} | 嵌套结构中优先使用局部变量 |
| 全局作用域 | 在根层级定义变量 | 可在文件任意位置访问 | @global-color: blue;.box { color: @global-color; }.text { color: @global-color; } | 全局变量应在文件顶部集中声明 |
| 变量查找机制 | — | 先查找局部,再向上查找全局 | @color: black;.container { @color: green; p { color: @color; } // green} | 类似 JavaScript 作用域链,局部覆盖全局 |
| 跨文件作用域 | @import "vars.less"; | 通过导入实现变量共享 | // vars.less@theme: #f00;// main.less@import "vars.less";body { color: @theme; } | 导入后变量进入当前文件作用域 |
2.3 变量作为配置项的实践
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 主题配置文件 | @import "config/theme.less"; | 集中管理视觉设计变量 | // theme.less@primary: #007bff;@success: #28a745;@danger: #dc3545; | 推荐创建独立的 variables.less 或 config.less |
| 响应式断点变量 | @breakpoint-sm: 576px; | 统一管理媒体查询阈值 | @breakpoint-md: 768px;@breakpoint-lg: 992px;@media (min-width: @breakpoint-md) { ... } | 提高响应式代码一致性 |
| 字体与间距系统 | @font-family-base, @spacing-unit | 构建设计系统基础 | @font-family: 'Arial', sans-serif;@spacing: 8px;.margin-bottom { margin-bottom: @spacing * 2; } | 便于全局调整设计规范 |
| 动态主题切换(配合 JS) | document.documentElement.style.setProperty | 运行时修改 CSS 变量(需结合 CSS 变量) | // Less 中输出 CSS 变量:root { --theme: @primary; } | 原生 Less 不支持运行时变量,需导出为 CSS Custom Properties |
第3章:嵌套规则(Nesting)
3.1 选择器嵌套
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 基本嵌套 | 在父选择器内书写子规则 | 模拟 HTML 层级结构,提升可读性 | .header { color: #333; .logo { font-size: 24px; } .nav { float: right; }} | 编译后生成 .header .logo 和 .header .nav |
| 多层嵌套 | 嵌套层级超过两层 | 组织复杂组件样式 | .card { border: 1px solid #ddd; .body { padding: 16px; .title { font-weight: bold; } }} | 避免过深嵌套(建议不超过 4 层),防止选择器权重过高 |
| 属性嵌套(简写) | property: { sub-property: value; } | 简化具有相同前缀的 CSS 属性 | .box { margin: { top: 10px; bottom: 20px; };} | 支持 border、font、padding 等复合属性 |
3.2 父选择器 & 的使用
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 引用父选择器 | & | 显式引用当前父选择器名称 | .btn { &.primary { background: blue; } &:hover { opacity: 0.8; } &-large { padding: 12px 24px; }} | 编译为 .btn.primary、.btn:hover、.btn-large |
| 伪类与伪元素 | &:hover, &::before | 为父选择器添加状态或装饰 | .link { color: #007bff; &:hover { color: darken(#007bff, 10%); } &::before { content: ">"; }} | 推荐使用 & 而非重复书写选择器 |
| BEM 命名支持 | &__element, &--modifier | 实现 BEM 架构风格 | .menu { &__item { padding: 8px; } &--vertical { display: block; }} | 提高组件化和命名一致性 |
多重 & 使用 | && | 重复父选择器(如禁用状态) | .btn { &&:disabled { opacity: 0.5; }} | 编译为 .btn.btn:disabled,用于提高优先级 |
3.3 嵌套带来的结构清晰性
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 结构对应 HTML | 嵌套结构匹配 DOM 树 | 提升样式与模板的可维护性 | .article { h1 { margin-bottom: 10px; } p { line-height: 1.6; } img { max-width: 100%; }} | 修改 HTML 时能快速定位对应样式 |
| 减少重复选择器 | 无需多次书写父级 | 降低代码冗余 | 不用写:.modal .header {}.modal .body {}而是嵌套书写 | 特别适合组件化开发 |
| 提高可读性 | 视觉上分组相关样式 | 团队协作更高效 | .dropdown { position: relative; &__toggle { cursor: pointer; } &__menu { display: none; } &:hover &__menu { display: block; }} | 新成员更容易理解样式逻辑 |
| 命名空间模拟 | 利用嵌套隔离样式作用域 | 防止全局污染 | .widget-a { color: red; .btn { background: yellow; }}.widget-b { ... } | 类似模块化思想,避免样式冲突 |
第4章:混合(Mixins)
4.1 基本混合
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 定义混合 | .mixin-name { ... } | 创建可复用的样式块 | .rounded { border-radius: 4px; overflow: hidden;} | 混合名以 . 开头,不生成独立 CSS 规则 |
| 调用混合 | .mixin-name; | 在规则中插入混合样式 | .card { .rounded; border: 1px solid #ddd;} | 编译后 .card 拥有 border-radius 和 overflow |
| 隐藏混合 | .helper() { ... } | 定义仅用于调用的混合(不输出) | .clearfix() { &::after { content: ""; display: table; clear: both; }} | 使用 () 表示该混合不直接输出 CSS |
4.2 带参数的混合
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 参数化混合 | .mixin(@param) { ... } | 使混合支持动态输入 | .size(@width, @height) { width: @width; height: @height;} | 提高灵活性,避免重复定义 |
| 调用带参混合 | .mixin(value1, value2); | 传入具体值使用混合 | .box { .size(100px, 50px);} | 参数顺序需与定义一致 |
| 多参数支持 | .mixin(@p1, @p2, ...) | 支持多个输入控制样式行为 | .margin(@top, @right, @bottom, @left) { margin: @top @right @bottom @left;} | 可用于封装常用布局模式 |
4.3 带默认值的参数
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 默认参数 | .mixin(@param: default-value) | 提供可选参数,简化调用 | .border(@color: #ccc, @width: 1px) { border: @width solid @color;} | 增强易用性,减少调用负担 |
| 部分传参 | .mixin(value); | 只传需要覆盖的参数,其余用默认值 | .btn { .border(#f00); } // color=red, width=1px | 适用于配置型混合 |
| 全覆盖 | .mixin(val1, val2); | 覆盖所有默认值 | .panel { .border(blue, 2px); } | 明确控制所有输出样式 |
4.4 混合的模式匹配与条件
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 模式匹配 | .mixin(keyword) { ... } | 根据参数值选择不同样式逻辑 | .icon(@type) when (@type = success) { color: green;}.icon(@type) when (@type = error) { color: red;} | 实现条件分支 |
条件守卫 when | when (@condition) | 添加调用条件 | .text-style(@size) when (@size > 16) { font-weight: bold;} | 支持 =、>、<、>=、<=、not |
| 多条件组合 | when (@a = b) and (@c < d) | 组合多个判断条件 | .alert(@level) when (@level = high) and (@theme = dark) { background: #f00;} | and 表示同时满足,, 表示或关系 |
| 默认分支 | .mixin(@x) { ... } | 无 when 的混合作为默认情况 | .size(@w) when (@w = large) { font-size: 24px; }.size(@w) { font-size: 16px; } | 最后一个无条件的混合作为 fallback |
4.5 命名空间与作用域
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 命名空间定义 | #namespace { ... } 或 .namespace { ... } | 组织相关混合,避免命名冲突 | #button { .primary { background: blue; } .small { padding: 4px; }} | 推荐使用 # 表示工具类命名空间 |
| 命名空间调用 | #namespace > .mixin; | 访问命名空间内的混合 | .btn-ok { #button > .primary;} | > 表示层级访问,可省略 |
| 私有混合 | .helper() { ... } | 命名空间内未暴露的辅助混合 | #layout { .col(@n) { width: (@n / 12) * 100%; } .flex() { display: flex; } // 可被调用} | 所有定义的混合默认可访问 |
| 作用域继承 | — | 混合可访问定义时所在作用域的变量 | @color: red;#theme { .text { color: @color; } } | 混合保留其定义环境的上下文 |
第5章:运算(Operations)
5.1 数值运算(+、-、*、/)
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 加法运算 | + | 计算两个数值之和 | @width: 100px;.box { width: @width + 20px; } | 编译为 width: 120px; |
| 减法运算 | - | 计算两个数值之差 | @margin: 20px;.item { margin: @margin - 5px; } | 注意与负号区分,减法需加空格或括号 |
| 乘法运算 | * | 将数值进行倍数计算 | @base: 8px;.padding-lg { padding: @base * 3; } | 编译为 padding: 24px; |
| 除法运算 | / | 执行数值除法 | @columns: 12;.col-6 { width: 100% / (@columns / 6); } | 除法必须用括号包裹,否则 / 不被识别为运算符 |
| 运算优先级 | (), * /, + - | 控制计算顺序 | .result { margin: (10px + 20px) * 2; } | 推荐使用括号明确优先级,避免歧义 |
5.2 颜色运算
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 颜色与数值运算 | color ± number | 调整颜色的 RGB 分量 | @base: #102030;.lighter { color: @base + #010101; } | 每个通道独立加减,不会溢出(自动截断) |
| 颜色与颜色运算 | color ± color | 合并或对比两种颜色 | @c1: #102030;@c2: #010101;.mix { color: @c1 + @c2; } | 各通道分别计算,结果为 #112131 |
| 颜色乘法 | color * number | 缩放颜色通道值(较少使用) | .dim { color: #888 * 0.8; } | 实际开发中多用 fade()、darken() 等函数替代 |
| 颜色除法 | color / number | 降低颜色通道值 | .softer { color: #ccc / 1.2; } | 同样建议使用函数替代,更语义化 |
| 混合优势 | — | 实现动态色调调整 | .highlight { background: @theme-color + #111100; } | 适用于生成渐变或阴影变体 |
5.3 单位运算与转换
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 相同单位运算 | unit ± unit | 对带单位的数值进行计算 | @height: 40px;.line { height: @height - 10px; } | 单位一致时正常计算 |
| 不同单位运算 | px + em, rem + % | 跨单位计算(需兼容) | @a: 10px;@b: 2em;.box { margin: @a + @b; } | Less 不自动转换单位,结果为 10px + 2em(非法),应避免 |
| 单位移除 | unit(value, new-unit) | 移除或更改数值单位 | @size: 20px;.fs { font-size: unit(@size, rem); } // 20rem | 常用于单位转换,但需手动控制逻辑 |
| 单位添加 | unit(number, unit) | 给无单位数添加单位 | @n: 2;.pad { padding: unit(@n, em); } | 编译为 padding: 2em; |
| 运算结果单位 | — | 结果单位由第一个操作数决定 | @a: 10px;@b: 2;.w { width: @a * @b; } // 20px | px * 无单位数 结果仍为 px,便于缩放 |
第6章:函数(Functions)
6.1 内置颜色函数(lighten、darken、fade 等)
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
lighten() | lighten(@color, 10%) | 使颜色更亮 | @base: #0000ff;.light { color: lighten(@base, 20%); } | 百分比表示亮度增加量,基于 HSL 模型 |
darken() | darken(@color, 15%) | 使颜色更暗 | .dark { color: darken(@base, 30%); } | 常用于 hover 状态颜色生成 |
fade() | fade(@color, 50%) | 设置颜色透明度(opacity) | .trans { color: fade(@base, 40%); } | 输出 rgba 值,不改变原有透明度 |
fadein() | fadein(@color, 10%) | 增加颜色透明度(变不透明) | .opaque { color: fadein(hsla(0,0%,0%,0.5), 20%); } | 适用于从半透明向不透明过渡 |
fadeout() | fadeout(@color, 10%) | 降低颜色透明度(变更透明) | .faded { color: fadeout(red, 30%); } | 与 fade() 不同,是相对减少 |
spin() | spin(@color, 10deg) | 调整颜色色相(Hue) | .shift { color: spin(#f00, 30deg); } | 正值顺时针,负值逆时针旋转色轮 |
mix() | mix(@color1, @color2, 60%) | 混合两种颜色,指定权重 | .blend { color: mix(#f00, #00f, 70%); } | 第三个参数为第一种颜色占比 |
6.2 字符串函数
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
escape() | escape('string') | URL 编码字符串 | .url { content: escape('https://example.com?q=less&v=1'); } | 将空格、&、= 等字符转义 |
e() | e("string") | 转义为纯 CSS 字符串(不加引号) | .icon { content: e("'"); } | 输出单引号字符,避免被引号包裹 |
%() | %('format', args...) | 格式化字符串(类似 sprintf) | .tip { content: %('New message from %s', 'John'); } | 支持 %s(字符串)、%d(数字)等占位符 |
replace() | replace('str', 'pattern', 'rep') | 替换字符串中的子串 | .path { data: replace('/api/v1/users', 'v1', 'v2'); } | 支持正则表达式(如 /v\d/)作为模式 |
| 字符串拼接 | @{var} | 变量插值(动态生成选择器或值) | @suffix: hover;.btn-@{suffix} { ... } | 编译为 .btn-hover,非常实用 |
6.3 类型判断函数
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
iscolor() | iscolor(@value) | 判断是否为颜色值 | .check { @type: iscolor(red) ? 'yes' : 'no'; } | 返回 true 或 false |
isnumber() | isnumber(@value) | 判断是否为数值 | .valid { when: isnumber(123px); } | 包括带单位和无单位的数字 |
isstring() | isstring(@value) | 判断是否为字符串 | .test { result: isstring("hello"); } | 字符串需用引号包裹 |
iskeyword() | iskeyword(@value) | 判断是否为关键字(非引号值) | .flag { check: iskeyword(normal); } | 如 normal、bold 等 |
isurl() | isurl(@value) | 判断是否为 URL 类型 | .link { valid: isurl(url(http://a.com)); } | 必须使用 url(...) 包裹 |
ispixel() | ispixel(@value) | 判断是否为 px 单位数值 | .size { px-only: ispixel(10px); } | 常用于响应式逻辑判断 |
6.4 数学函数
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
ceil() | ceil(3.2) | 向上取整 | .rows { count: ceil(10 / 3); } // 4 | 常用于栅格系统行数计算 |
floor() | floor(3.8) | 向下取整 | .cols { span: floor(5.9); } // 5 | 获取整数部分 |
round() | round(3.6) | 四舍五入 | .val { r: round(2.49); } // 2 | 可指定小数位:round(2.456, 2) → 2.46 |
percentage() | percentage(0.5) | 将数字转为百分比字符串 | .width { width: percentage(1/2); } // 50% | 输入为 0~1 的小数 |
min() | min(10px, 5%) | 返回多个值中的最小值 | .gap { margin: min(20px, 5vw); } | 多用于响应式设计 |
max() | max(100px, 50%) | 返回多个值中的最大值 | .container { width: max(320px, 80%); } | 防止内容过小 |
abs() | abs(-10px) | 返回绝对值 | .dist { offset: abs(-20px); } // 20px | 消除负值影响 |
第7章:继承与扩展(Extend)
7.1 extend 关键字的使用
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 基本继承 | &:extend(selector) | 复用已有选择器的样式,减少重复 | .alert { color: #a94442; background: #f2dede; }.error { &:extend(.alert); } | 编译后 .error 拥有 .alert 的所有样式 |
| 属性继承 | selector:extend(.base all) | 继承指定选择器的所有匹配规则 | .btn { padding: 10px; border: 1px solid #ccc; }.btn-small:extend(.btn all) {} | all 表示继承所有匹配的规则,包括复合选择器 |
| 多重继承 | &:extend(.a, .b) | 同时继承多个选择器的样式 | .success { color: green; }.large { font-size: 20px; }.big-success { &:extend(.success, .large); } | 生成组合选择器,合并所有样式 |
| 选择器合并 | — | 减少 CSS 输出体积 | .nav-item { margin: 5px; }.active { &:extend(.nav-item); } | 编译为 .nav-item, .active { margin: 5px; },而非复制样式 |
| 限制使用场景 | 避免过度使用 | 适用于样式完全相同的情况 | — | 若只需部分样式,应使用 mixin 而非 extend |
7.2 链式继承
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 继承传递性 | A → B → C | 通过中间选择器间接继承样式 | .base { color: red; }.mid:extend(.base) {}.child:extend(.mid) {} | 编译后 .child 也拥有 .base 的样式 |
| 多层级复用 | — | 构建样式继承体系 | .btn { padding: 10px; }.btn-primary:extend(.btn) {}.btn-primary-lg:extend(.btn-primary) {} | 生成 .btn, .btn-primary, .btn-primary-lg { padding: 10px; } |
| 继承合并优化 | — | Less 自动合并所有继承路径 | .icon { display: inline-block; }.icon-sm:extend(.icon) {}.icon-red:extend(.icon-sm) {} | 输出为 .icon, .icon-sm, .icon-red { ... } |
| 注意可读性 | — | 过深链式降低维护性 | — | 建议不超过 3 层,避免逻辑混乱 |
| 与混合对比 | — | extend 是 CSS 层面合并,mixin 是代码复制 | 使用 extend 可减少生成 CSS 大小 | 在需要生成独立类名时优先用 mixin |
7.3 %placeholder 伪类的使用
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 定义占位符 | %placeholder { ... } | 创建不输出 CSS 的样式模板 | %clearfix { &::after { content: ""; display: table; clear: both; }} | 仅作为继承目标,不生成独立规则 |
| 被 extend 引用 | .selector:extend(%placeholder) | 继承占位符样式,避免冗余输出 | .group:extend(%clearfix) {} | 编译后仅 .group 拥有 clearfix 样式 |
| 多处复用 | — | 多个选择器继承同一占位符 | .left:extend(%rounded) {}.right:extend(%rounded) {} | 输出 .left, .right { border-radius: 4px; } |
| 与 mixin 对比 | — | 占位符继承更节省 CSS 体积 | %rounded { border-radius: 4px; }使用 extend:输出一次 使用 mixin:每处调用都复制 | 大量复用时推荐 extend + % |
| 命名规范 | %helper-name | 提高可读性,表明用途 | %invisible { position: absolute; left: -9999px; } | 推荐以 % 开头,语义化命名 |
第8章:条件与循环(Guards 与 Loops)
8.1 When 条件守卫
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 基本条件守卫 | .mixin(@a) when (@a > 10) { ... } | 根据参数条件决定是否应用混合 | .text(@size) when (@size > 16) { font-weight: bold;}.title { .text(18); } | 只有满足条件时才插入样式 |
| 等值判断 | when (@color = blue) | 匹配特定参数值 | .border(@color) when (@color = red) { border: 2px solid red;} | 使用 = 表示相等,不区分大小写 |
| 逻辑与(and) | when (@a = b) and (@c < d) | 多个条件同时满足 | .alert(@level, @theme) when (@level = high) and (@theme = dark) { color: white; background: #f00;} | and 表示”且”关系 |
| 逻辑或(,) | when (@a = x), (@b = y) | 满足任一条件即可 | .size(@s) when (@s = small), (@s = tiny) { font-size: 12px;} | 逗号 , 表示”或” |
| 否定条件 | when not (@a > 10) | 条件不成立时匹配 | .default(@x) when not (@x = primary) { color: #666;} | not 用于取反判断 |
8.2 使用递归实现循环
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 递归混合定义 | .loop(@i) when (@i > 0) { ... .loop(@i - 1); } | 通过自身调用实现循环逻辑 | .generate-columns(12);.generate-columns(@n) when (@n > 0) { .col-@{n} { width: (@n / 12) * 100%; } .generate-columns(@n - 1);} | 必须设置终止条件防止无限递归 |
| 终止条件 | .loop(@i) when (@i = 0) { } | 结束递归调用 | .generate-columns(@n) when (@n = 0) { } | 空定义或基础情况,避免无限循环 |
| 参数递减 | @counter: @counter - 1 | 控制循环进度 | .list-styles(5);.list-styles(@i) when (@i > 0) { li:nth-child(@{i}) { opacity: (@i * 0.2); } .list-styles(@i - 1);} | 常用于生成序列样式 |
| 嵌套循环模拟 | 双层递归 | 实现二维结构生成 | .grid-row(3);.grid-row(@r) when (@r > 0) { .row-@{r} { .grid-cell(4); } .grid-row(@r - 1);} | 复杂度高,需谨慎使用 |
| 性能考量 | — | 避免过深递归 | 设置 @n <= 100 等安全上限 | 过多递归可能导致编译缓慢或内存溢出 |
8.3 遍历与动态样式生成
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 动态类名生成 | @{variable} | 结合递归生成系列类 | .generate-buttons(primary, secondary, success);.generate-buttons(@list) when (length(@list) > 0) { @first: extract(@list, 1); .btn-@{first} { background: @@first-color; } .generate-buttons(remove(@list, @first));} | 使用 extract() 和 remove() 操作列表 |
| 列表遍历 | length(), extract() | 处理参数列表 | @colors: red, blue, green;.colorize(@i: 1) when (@i <= length(@colors)) { .item-@{i} { color: extract(@colors, @i); } .colorize(@i + 1);}.colorize(); | 实现数组式遍历 |
| 响应式断点生成 | 循环创建媒体查询 | 批量生成响应式规则 | .make-grid(12);.make-grid(@n) when (@n > 0) { @media (min-width: @n * 60px) { .col-@{n} { float: left; width: 100%; } } .make-grid(@n - 1);} | 提高响应式系统可维护性 |
| 样式工厂模式 | 通用生成逻辑 | 创建可复用的代码生成器 | .create-icons(@icons);// 定义图标映射并循环生成 | 适用于图标、按钮、表单等组件批量生成 |
| 调试技巧 | // 注释 或 debug: true | 查看递归过程 | 在递归中添加 // step: @i 注释 | 复杂逻辑建议分步测试,避免错误累积 |
第9章:命名空间与模块化
9.1 命名空间的定义与调用
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 定义命名空间 | #namespace { ... } 或 .namespace { ... } | 将相关变量、混合等组织在一起 | #button { @color: blue; .primary { background: @color; } .small { padding: 4px 8px; }} | 推荐使用 # 表示工具类命名空间,. 表示样式块 |
| 调用命名空间成员 | #namespace > .mixin; 或 .namespace > variable; | 访问命名空间内的混合或变量 | .btn-ok { #button > .primary; color: #button[@color];} | > 可省略;变量需用 [] 语法访问 |
| 私有成员 | 无前缀的混合或变量 | 仅在命名空间内部使用 | #utils { .to-rem(@px) { (@px / 16px) * 1rem; } .text-lg { font-size: .to-rem(20px); }} | 外部无法直接调用 .to-rem(),提高封装性 |
| 嵌套命名空间 | #a { #b { .c { ... } } } | 创建多层级结构 | #layout { #grid { .col-12 { width: 100%; } }} | 调用:#layout > #grid > .col-12; |
| 避免命名冲突 | — | 隔离不同模块的标识符 | #modal-v1 { .close { ... } }#modal-v2 { .close { ... } } | 不同版本或组件可共存 |
9.2 模块化组织大型项目
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 按功能拆分文件 | @import "vars.less"; | 将样式拆分为独立模块 | // main.less@import "config/variables";@import "layout/grid";@import "components/modal"; | 文件扩展名可省略 |
| 配置模块 | variables.less, themes.less | 集中管理设计变量 | // variables.less@primary-color: #007bff;@font-family: 'Arial', sans-serif; | 所有模块共享配置 |
| 布局模块 | layout.less, grid.less | 定义页面结构样式 | // grid.less.row { display: flex; flex-wrap: wrap; }.col { flex: 1; } | 可被多个页面复用 |
| 组件模块 | buttons.less, forms.less | 封装 UI 组件 | // buttons.less.btn { padding: 8px 16px; .rounded; } | 遵循单一职责原则 |
| 工具模块 | mixins.less, helpers.less | 提供通用混合和函数 | // mixins.less.clearfix() { &::after { content:""; display:table; clear:both } } | 被其他模块频繁引用 |
9.3 封装可复用组件库
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 组件封装 | 命名空间 + 参数化混合 | 创建可配置的 UI 组件 | #alert { .style(@bg, @color) { background: @bg; color: @color; padding: 10px; border-radius: 4px; } .success { .style(green, white); } .error { .style(red, white); }} | 支持主题定制和扩展 |
| 主题支持 | 变量注入 + extend | 实现多主题切换 | // themes/dark.less@primary: #333;@text: #fff;// 导入后自动应用 | 通过切换导入文件实现主题 |
| 构建输出控制 | @import (reference) | 引用但不输出样式 | @import (reference) "library.less";.my-btn { #lib > .btn-primary; } | 避免重复输出组件库样式 |
| 版本管理 | 文件命名或命名空间版本 | 兼容不同版本组件 | #carousel-v2 { ... } 或 carousel/2.0.less | 便于渐进式升级 |
| 文档与示例 | 注释 + 示例文件 | 提高组件库可用性 | // 按钮组件// 调用方式:.btn, .btn-large.btn { ... } | 团队协作必备 |
第10章:作用域与加载机制
10.1 文件导入(@import)
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 基本导入 | @import "filename"; | 将其他 Less 文件内容合并到当前文件 | @import "variables";@import "mixins";@import "components/buttons"; | 文件扩展名 .less 可省略 |
| 导入 CSS 文件 | @import "style.css"; | 直接引入标准 CSS 文件 | @import "normalize.css"; | 不会编译,原样输出 @import "normalize.css"; 到 CSS |
| 条件导入 | @import (less) "file.css"; | 强制将非 .less 文件作为 Less 解析 | @import (less) "theme.css"; | 用于导入包含 Less 语法的 CSS 文件 |
| 延迟导入 | @import 放在规则内部 | 延迟导入文件直到被调用 | .theme-dark { @import "dark-theme";} | dark-theme.less 仅在 .theme-dark 被使用时编译 |
| 导入通配符 | — | Less 原生不支持 @import "folder/*" | 需借助构建工具(如 Webpack)实现 | 原生 Less 不支持目录导入 |
10.2 作用域查找规则
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 局部优先 | @var 在嵌套中查找 | 变量查找遵循”就近原则” | @color: red;.container { @color: blue; p { color: @color; } // blue} | 局部变量覆盖全局变量 |
| 全局回退 | @var 未在局部定义时 | 向上查找直至根作用域 | @base: 16px;.text { font-size: @base; } // 16px | 全局变量可在任意层级访问 |
| 混合查找 | .mixin 调用时 | 先查局部,再查全局 | .helper() { opacity: 0.5; }.box { .helper() { transform: scale(0.9); } .helper; // 调用局部} | 局部混合优先于全局 |
| 导入作用域合并 | @import 后变量进入当前文件 | 导入文件的变量和混合可被使用 | // vars.less: @primary: #007bff;@import "vars";.btn { background: @primary; } | 导入即合并作用域 |
| 命名空间隔离 | #ns > .mixin; | 命名空间内变量不污染全局 | #theme { @color: green; }// 全局无法直接访问 @color | 访问需通过 #theme[@color] |
10.3 导入选项(reference、inline 等)
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
reference | @import (reference) "file"; | 引用文件但不输出其样式 | @import (reference) "bootstrap.less";.my-btn { .btn; .btn-primary; } | 仅复用混合和变量,避免重复 CSS |
inline | @import (inline) "file.css"; | 将外部 CSS 直接插入输出文件 | @import (inline) "reset.css"; | 原内容插入,不进行编译处理 |
less | @import (less) "file.ext"; | 强制作为 Less 文件解析 | @import (less) "theme.min"; | 适用于无 .less 扩展名的 Less 文件 |
css | @import (css) "file.less"; | 强制作为 CSS 文件处理 | @import (css) "print.less"; | 输出 @import url(file.less); 到 CSS |
once | @import (once) "file"; | 确保文件只被导入一次(默认行为) | @import (once) "vars"; // 默认,可省略 | 防止重复导入,避免冗余 |
multiple | @import (multiple) "file.css"; | 允许同一文件被多次导入 | @import (multiple) "print.css"; | 用于需要多次引入的 CSS(如打印样式) |
第11章:高级特性与技巧
11.1 Lazy Loading(延迟加载)
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 变量延迟加载 | 在使用时才确定值 | 允许在定义后覆盖变量 | @color: green;.module { @color: black; .element { color: @color; } // black}@color: white; // 不影响已编译的 .module | 变量取其最后定义前的值 |
| 混合延迟解析 | 混合调用时查找定义 | 混合可在调用后定义 | .use { .mixin; }.mixin { color: red; } | 编译通过,输出 .use { color: red; } |
| 作用域继承延迟 | 嵌套中访问外部变量 | 变量值以最终作用域为准 | @var: global;.outer { @var: local; .inner { .test { value: @var; } // local }} | 支持动态作用域查找 |
| 文件导入延迟 | @import 放在选择器内 | 延迟导入文件直到被使用 | .theme-dark { @import "dark-theme";} | dark-theme.less 仅在 .theme-dark 出现时编译 |
| 注意覆盖顺序 | — | 理解”后定义优先”规则 | @size: 10px;.a { font-size: @size; }@size: 12px;.b { font-size: @size; } // 12px | 适用于主题覆盖等场景 |
11.2 Merge 属性(逗号/空格合并)
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 逗号合并 | property+: value | 将多个值用逗号连接 | .tag { box-shadow+: inset 0 0 0 1px black; box-shadow+: 0 2px 4px rgba(0,0,0,0.3);} | 输出 box-shadow: inset 0 0 0 1px black, 0 2px 4px rgba(0,0,0,0.3); |
| 空格合并 | property++: value | 将多个值用空格连接 | .icon { background+: url(icon.png); background++: no-repeat;} | 输出 background: url(icon.png) no-repeat; |
| 多值组合 | +:, ++: | 构建复合属性值 | .gradient { background+: linear-gradient(to right, red, blue); background++: url(overlay.png);} | 生成 background: linear-gradient(...) url(...); |
| 与普通赋值区别 | property: value | 覆盖而非合并 | 使用 : 会覆盖之前定义 | 合并操作符用于增量添加 |
| 应用场景 | — | 图标背景、多重阴影、字体栈 | .font { font-family+: Arial; font-family++: sans-serif;} | 提高样式组合灵活性 |
11.3 JavaScript 表达式(通过 ~"")
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| JS 表达式执行 | ~"javascript code" | 在编译时执行 JS 逻辑 | .width { width: ~"(Math.random() * 100)%";} | 输出随机宽度,如 width: 45.6%; |
| 字符串拼接 | ~"'string'" | 输出不带引号的字符串 | .quote { content: ~"'"; } | 生成单引号字符 |
| 动态计算 | ~"parseInt('10px') * 2" | 执行复杂数值计算 | .size { font-size: ~"(16 * 1.25)px"; // 20px} | 需确保 JS 表达式返回有效 CSS 值 |
| 访问环境变量 | ~"process.env.NODE_ENV" | 读取构建环境信息 | .env { body: ~"(process.env.NODE_ENV === 'dev' ? 'dev-mode' : '')";} | 需在 Node.js 环境下编译 |
| 安全风险 | — | 可能执行任意代码 | 避免在不可信环境中使用 | 仅用于开发构建阶段,禁用用户输入 |
11.4 自定义函数(通过 JavaScript 扩展)
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 注册自定义函数 | less.functions.add() | 在 JS 中扩展 Less 函数 | less.functions.add('sqrt', function(n) { return Math.sqrt(n.value);}); | 需在编译器环境(如 Node.js)中注册 |
| 调用自定义函数 | sqrt(16) | 在 Less 文件中使用扩展函数 | .result { value: sqrt(25); } // 5 | 编译时调用注册的 JS 函数 |
| 参数处理 | n.value, n.unit | 获取 Less 值的数值和单位 | add('px2rem', function(px) { let val = px.value / 16; return new less.tree.Dimension(val, 'rem');}); | 需返回 tree 类型对象 |
| 返回值封装 | new less.tree.* | 返回正确的 AST 节点类型 | 数值用 Dimension,颜色用 Color 等 | 确保类型正确,避免编译错误 |
| 移除函数 | less.functions.remove('name') | 注销已注册函数 | less.functions.remove('sqrt'); | 用于模块清理或热重载 |
第12章:项目实战与最佳实践
12.1 构建可维护的主题系统
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 主题变量文件 | themes/dark.less, themes/light.less | 集中定义主题颜色、字体等 | // themes/dark.less@primary: #333;@text: #fff;@bg: #1a1a1a; | 每个主题一个独立文件 |
| 变量覆盖机制 | @import 顺序控制 | 后导入的变量覆盖先定义的 | @import "config/variables"; // 默认主题@import "themes/@{theme}.less"; // 动态主题 | 利用 Less 的”后定义优先”规则 |
| CSS 变量桥接 | 输出 --var 到 :root | 支持运行时主题切换 | :root { --primary: @primary; --text: @text;}.btn { color: var(--primary); } | 结合 JS 动态切换 data-theme |
| 命名空间封装 | #theme > .apply(); | 提供统一的主题应用接口 | #theme { .apply() { body { color: @text; bg: @bg; } }}.dark-mode { #theme > .apply(); } | 提高调用一致性 |
| 多主题编译 | 构建脚本生成多个 CSS | 输出 app-dark.css, app-light.css | 使用 Webpack 多入口或条件编译 | 适用于静态部署场景 |
12.2 响应式框架封装
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 断点变量定义 | @breakpoint-sm: 576px; | 统一管理媒体查询阈值 | @breakpoints: { sm: 576px, md: 768px, lg: 992px}; | 避免硬编码,提高一致性 |
| 媒体查询混合 | .mq(@bp) { @media ... } | 封装常用响应式逻辑 | .mq(@min, @max) when (@max) { @media (min-width: @min) and (max-width: @max) { @content; }} | 使用 @content 插入嵌套规则 |
| 栅格系统生成 | 递归生成列类 | 自动生成 .col-1 到 .col-12 | .make-grid(12);.make-grid(@n) when (@n > 0) { .col-@{n} { width: (100% / 12) * @n; } .make-grid(@n - 1);} | 支持灵活布局 |
| 移动优先设计 | 从 min-width 开始 | 符合现代响应式实践 | .responsive-text { font-size: 14px; .mq(md) { font-size: 16px; }} | 小屏优先,逐步增强 |
| 工具类生成 | 批量创建 mt-1, p-2 等 | 提高开发效率 | .make-spacers() { .loop(@i: 1) when (@i <= 10) {.mt-@{i} { margin-top: @i * 4px; } .loop(@i + 1); }} | 类似 Tailwind 的间距系统 |
12.3 与构建工具(Webpack、Vite)集成
| 相关特性/配置 | 语法/使用方式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| Webpack 集成 | webpack.config.js | 编译 Less 文件 | module: { rules: [ { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] } ]} | 确保安装 less 和 less-loader |
| Vite 集成 | vite.config.js | 快速编译与热更新 | export default { css: { preprocessorOptions: { less: { javascriptEnabled: true, additionalData: '@import "src/vars.less";' } } }} | additionalData 自动导入全局变量 |
| 全局变量注入 | less-loader options | 避免重复导入变量文件 | { lessOptions: { modifyVars: { '@primary': '#007bff' } }} | 支持运行时覆盖主题 |
| Source Map 支持 | devtool: 'source-map' | 调试时定位原始 Less 代码 | less-loader: { options: { sourceMap: true }} | 提高开发调试效率 |
| Tree Shaking | 配合命名空间 | 移除未使用的样式 | 使用 @import (reference) 引用组件库 | 减少最终 CSS 体积 |
12.4 性能优化建议
| 相关特性/配置 | 方法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 避免深层嵌套 | 减少选择器层级 | 降低 CSS 权重,提高渲染性能 | — | 建议不超过 3-4 层,如 .component .header .title |
| 合理使用 extend | 优先于 mixin 复用 | 减少生成的 CSS 体积 | — | extend 合并选择器,mixin 复制代码 |
| 模块化导入 | 按需加载组件样式 | 避免导入未使用的代码 | @import "components/button"; 而非整个 components.less | 按需引入,减小输出 |
| 缓存构建结果 | Webpack/Vite 缓存 | 加快二次编译速度 | — | 构建工具默认支持,确保配置正确 |
| 压缩输出 CSS | 生产环境启用压缩 | 减小文件体积 | lessc --clean-css 或构建工具自动压缩 | 生产环境必备 |
| 减少递归深度 | 控制循环次数 | 防止编译时间过长 | — | 避免生成超过 100 个类的递归循环 |
| 使用 CSS 变量替代 | 运行时动态样式 | 减少预编译生成的变体 | --primary 替代多套 .theme-dark .btn | 如主题色用 --primary 而非生成多套变体 |