Skip to content

less_quick_guide

LESS (Leaner Style Sheets) 是一个成熟且强大的 CSS 预处理器。它通过变量、混合集(mixins)、运算和函数等动态行为扩展了 CSS。这使你能够编写更易于维护、主题化和可重用的 CSS。LESS 代码会被编译成 Web 浏览器能理解的标准 CSS。它被设计得尽可能像 CSS,使得熟悉 CSS 的人学习曲线非常平缓。

CSS 预处理器是一种脚本语言,它扩展了标准 CSS 的功能。它提供了 CSS 本身不具备的功能,然后这些功能会被处理并编译成常规的 CSS 语法。这使得开发者能够编写更组织化、高效和动态的样式表。

LESS 为现代 Web 开发提供了几项优势:

  • 可维护性: 变量和混合集减少了重复,使全局更改更容易。在一个地方更新颜色或字体,它就会传播到整个样式表中。
  • 可重用性: 混合集允许你封装和重用一组 CSS 声明,推广 DRY (Don’t Repeat Yourself) 原则。
  • 组织性: 嵌套规则模仿 HTML 结构,使样式表更具可读性和组织性。导入部分文件有助于模块化 CSS。
  • 动态能力: 运算、函数和控制流结构(守卫、循环)允许进行复杂的计算和条件样式。
  • 效率: 编写更少的代码,这些代码会编译成标准 CSS,可能加快开发时间。

LESS 最初由 Alexis Sellier 于 2009 年设计,用 Ruby 编写。后来,它被移植到 JavaScript,这显著增加了其采用率,允许进行客户端编译(用于开发)并与基于 Node.js 的构建工具集成。LESS 是一个开源项目,多年来一直是一个稳定可靠的预处理器。

  • 变量: 定义可重用的值,用于颜色、字体、尺寸等(例如,@primary-color: #3498db;)。
  • 混合集(Mixins): 将一个规则集中的一组属性包含到另一个规则集中。参数化混合集接受参数以获得更大的灵活性。
  • 嵌套: 在彼此内部嵌套 CSS 规则,模仿 HTML 结构,使代码更简洁。
  • 运算: 对数值和颜色执行算术运算(+, -, *, /)。
  • 函数: 内置函数,用于颜色操作、数学计算、字符串处理和类型检查。
  • 导入: 将 LESS 代码分成多个文件并导入它们。
  • 扩展(Extend): 在选择器之间共享 CSS 属性,而无需复制代码,从而生成更高效的 CSS。
  • 守卫(Guards): 根据表达式为混合集和 CSS 规则实现条件逻辑。
  • 循环: 使用递归混合集和守卫创建重复的 CSS 模式。
  • 生成浏览器兼容的 CSS。
  • 通过嵌套和导入增强代码组织性和可读性。
  • 通过变量和混合集加快维护速度。
  • 允许强大的抽象和代码重用。
  • 通过运算和函数简化复杂的 CSS 任务。
  • 编译步骤: 需要将 LESS 编译为 CSS,这会增加开发工作流程中的一层(尽管现代工具可以自动化此过程)。
  • 学习曲线: 虽然语法类似 CSS,但理解预处理器的概念(变量、混合集、作用域)需要一些初步的努力。
  • 调试: 调试有时会更棘手,因为错误可能源于 LESS 代码,但在编译后的 CSS 中显现出来(Source map 在这方面有很大帮助)。
  • 过度抽象: 如果滥用深层嵌套或复杂混合集等功能,可能会使样式表过度复杂化。

要使用 LESS,你需要将 .less 文件编译成标准 .css 文件。最常见的方法是使用 LESS 编译器,它运行在 Node.js 上。

  • Node.js 和 npm: LESS 是一个 Node.js 包。你需要安装 Node.js(其中包含 npm,Node Package Manager)在你的系统上。从 nodejs.org 下载(大多数用户推荐 LTS 版本)。
  • 浏览器支持(针对编译后的 CSS): LESS 生成的 CSS 是标准 CSS,适用于所有现代浏览器(Chrome、Firefox、Safari、Edge 等)。

你可以全局安装 LESS 编译器(lessc),也可以将其作为项目依赖。

步骤 1:安装 Node.js 和 npm

如果尚未安装,请从 nodejs.org 下载并安装 Node.js。这将同时安装 npm。

步骤 2:安装 LESS

打开终端或命令提示符,选择以下方法之一:

全局安装(推荐用于在任何地方使用命令行):

npm install -g less

这使得 lessc 命令可以在你的系统上全局使用。

本地安装(推荐用于特定项目和构建工具集成):

在终端中导航到你的项目目录并运行:

npm install --save-dev less

这将 LESS 安装为你的项目的开发依赖,并允许你将其与构建脚本一起使用(例如,在 package.json 脚本中或与 Webpack 或 Gulp 等工具一起使用)。

步骤 3:验证安装

安装后,你可以通过检查版本来验证它(如果全局安装):

lessc -v

这应该会输出安装的 LESS 编译器版本。

让我们创建一个简单的 LESS 示例。

1. 创建 HTML 文件(例如,index.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LESS Example</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h1>Welcome to LESS</h1>
<p>This is styled with LESS!</p>
</body>
</html>

2. 创建 LESS 文件(例如,style.less):

@primary-color: #3498db;
@secondary-color: #2ecc71;
@text-color: #333;
body {
font-family: Arial, sans-serif;
color: @text-color;
}
h1 {
color: @primary-color;
}
p {
color: @secondary-color;
font-size: 1.1em;
}

3. 编译 LESS 文件:

打开终端,导航到你保存这些文件的目录,然后运行:

lessc style.less style.css

此命令告诉 LESS 编译器将 style.less 作为输入,并将编译后的 CSS 输出到 style.css。

4. 检查编译后的 CSS(style.css):

生成的 style.css 文件将如下所示:

body {
font-family: Arial, sans-serif;
color: #333333;
}
h1 {
color: #3498db;
}
p {
color: #2ecc71;
font-size: 1.1em;
}

在 Web 浏览器中打开 index.html。你将看到标题和段落根据你在 LESS 文件中定义并编译到 style.css 中的规则进行样式化。

在实际项目中,LESS 编译通常通过 Webpack (使用 less-loader)、Parcel、Gulp (使用 gulp-less) 或 npm 脚本等工具集成到自动化构建流程中。

LESS 中的嵌套允许你以层次结构的方式编写 CSS 选择器,这种方式模仿了 HTML 的结构。通过将相关样式分组在一起,这使得你的样式表更组织化、可读性更高且更易于维护。

你无需重复编写父选择器,而是可以将子选择器嵌套在其父规则内部。

考虑以下 HTML 结构:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Nested Rules Example</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<nav class="main-nav">
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#about">About</a></li>
<li class="active"><a href="#services">Services</a></li>
</ul>
</nav>
<article class="content">
<header>
<h1>Main Title</h1>
</header>
<p>Some introductory text.</p>
</article>
</body>
</html>

现在,让我们在 style.less 中编写相应的 LESS 代码:

@link-color: #007bff;
@active-color: #ff4500;
.main-nav {
background-color: #f0f0f0;
padding: 10px;
ul {
list-style-type: none;
margin: 0;
padding: 0;
li {
display: inline-block;
margin-right: 15px;
a {
text-decoration: none;
color: @link-color;
&:hover {
text-decoration: underline;
}
}
// 使用父选择器 '&' 来对修改后的父元素应用样式
&.active a {
color: @active-color;
font-weight: bold;
}
}
}
}
.content {
padding: 20px;
header {
border-bottom: 1px solid #ccc;
margin-bottom: 15px;
h1 {
color: #333;
font-size: 2em;
}
}
p {
font-size: 1em;
line-height: 1.6;
}
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是:

.main-nav {
background-color: #f0f0f0;
padding: 10px;
}
.main-nav ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.main-nav ul li {
display: inline-block;
margin-right: 15px;
}
.main-nav ul li a {
text-decoration: none;
color: #007bff;
}
.main-nav ul li a:hover {
text-decoration: underline;
}
.main-nav ul li.active a {
color: #ff4500;
font-weight: bold;
}
.content {
padding: 20px;
}
.content header {
border-bottom: 1px solid #ccc;
margin-bottom: 15px;
}
.content header h1 {
color: #333;
font-size: 2em;
}
.content p {
font-size: 1em;
line-height: 1.6;
}

在嵌套规则中,& (ampersand) 字符是一个特殊选择器,它引用当前的父选择器。它通常用于:

  • 应用伪类(例如,&:hover, &:focus)。
  • 为父元素应用修饰类(例如,&.active, BEM 方法论中的 &—modifier)。
  • 前置选择器(例如,body.dark-theme & { … })。

嵌套极大地改善了 LESS 文件的结构,通过视觉上分组相关样式,使其更易于阅读和维护。

在浏览器中打开 HTML 文件。导航和内容部分将根据嵌套规则进行样式化,这演示了 LESS 如何以反映 HTML 层次结构的方式组织样式。

LESS 允许你将 CSS @规则(指令),如 @media 或 @supports 嵌套在选择器内部。当 LESS 编译这些嵌套指令时,它会采用一种称为“冒泡”(bubbling)的过程。这意味着嵌套指令会被移动到 CSS 输出的顶层,在其父选择器之外,但指令内的选择器会与父选择器正确组合。

此功能对于以更有组织和上下文感知的方式编写响应式样式或特性查询特别有用,它将一个组件的样式及其响应式变体分组在一起。

让我们演示嵌套 @media 查询。

HTML (index.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nested Directives Example</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="widget">
<h2>Widget Title</h2>
<p>This is some content within the widget.</p>
</div>
</body>
</html>

LESS (style.less):

.widget {
width: 90%;
margin: 20px auto;
padding: 15px;
background-color: #f0f0f0;
border: 1px solid #ccc;
h2 {
color: #333;
margin-top: 0;
}
p {
color: #555;
}
// 嵌套 @media 查询
@media (min-width: 768px) {
width: 600px; // 在较大屏幕上的 Widget 宽度
padding: 25px;
h2 {
font-size: 1.8em;
}
}
// 另一个用于不同条件的嵌套 @media 查询
@media (max-width: 480px) {
p {
font-size: 0.9em;
}
// 嵌套在 @media 内部的 @supports
@supports (display: grid) {
background-color: #e0e0e0; // 在小屏幕上如果支持 grid 则背景不同
}
}
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将显示指令是如何冒泡的:

.widget {
width: 90%;
margin: 20px auto;
padding: 15px;
background-color: #f0f0f0;
border: 1px solid #ccc;
}
.widget h2 {
color: #333;
margin-top: 0;
}
.widget p {
color: #555;
}
@media (min-width: 768px) {
.widget {
width: 600px;
padding: 25px;
}
.widget h2 {
font-size: 1.8em;
}
}
@media (max-width: 480px) {
.widget p {
font-size: 0.9em;
}
@supports (display: grid) {
.widget {
background-color: #e0e0e0;
}
}
}
  • 嵌套指令(@media, @supports 等)在编译后的 CSS 中会移动到顶层。
  • 冒泡指令内的选择器会正确地以其父上下文为前缀(例如,示例中的 .widget)。
  • 这使得组件特定的响应式样式或特性查询与其基本样式一起放在 LESS 文件中,从而改善组织性。
  • 多个嵌套指令,或指令嵌套在彼此内部(例如 @supports 在 @media 内部),也会正确冒泡。

当你查看 index.html 并调整窗口大小时:

  • 在宽度大于 768px 的屏幕上,widget 将宽 600px,有更多的内边距,并且其 h2 会更大。
  • 在宽度小于 480px 的屏幕上,widget 的段落文本会变小。如果浏览器支持 CSS Grid,widget 的背景在这些小屏幕上也会改变。

这演示了冒泡如何帮助以结构化的方式管理复杂的条件样式。

LESS 允许你在样式表中直接执行算术运算(+, -, *, /)。这些运算可以应用于数字、尺寸(带有单位的值,如 px, em, %),甚至是颜色。

运算是一个强大的特性,用于在样式值之间创建动态关系,使你的 CSS 更灵活和易于维护。

单位处理:

  • LESS 尝试推断输出单位。例如,10px + 5px 的结果是 15px。
  • 兼容单位之间的运算(例如,2in + 5cm)将转换为第一个操作数的单位。
  • 将尺寸乘以或除以无单位数字会缩放该尺寸(例如,10px * 2 的结果是 20px)。
  • 将尺寸除以另一个尺寸会得到一个无单位数字(例如,10px / 2px 的结果是 5)。
  • 你可以使用 LESS 选项(strictUnits 和 strictMath)控制单位转换和数学严格性。

运算优先级:

乘法(*)和除法(/)的优先级高于加法(+)和减法(-)。可以使用括号 () 来明确控制计算顺序,就像在标准数学中一样。

让我们通过一个示例来说明运算。

HTML (index.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LESS Operations Example</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">
<header class="main-header">Header</header>
<article class="content-area">Content</article>
<aside class="sidebar">Sidebar</aside>
</div>
</body>
</html>

LESS (style.less):

@base-font-size: 16px;
@base-spacing: 20px;
@primary-color: #3498db; // 蓝色
.container {
width: 80%;
max-width: 1000px;
margin: @base-spacing auto;
font-size: @base-font-size;
}
.main-header {
padding: @base-spacing / 2; // 10px
background-color: @primary-color;
color: white;
font-size: @base-font-size * 1.5; // 24px
border-bottom: (@primary-color - #222) 3px solid; // 更深的边框颜色
}
.content-area {
width: (100% / 3) * 2; // 大约 66.6666%
float: left;
padding: @base-spacing;
background-color: #f9f9f9;
}
.sidebar {
width: (100% / 3) - @base-spacing; // 大约 33.3333% 减去间距以留空隙
float: right;
padding: @base-spacing;
background-color: #eee;
// 颜色运算
color: @primary-color + #333; // 稍微提亮蓝色
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是:

.container {
width: 80%;
max-width: 1000px;
margin: 20px auto;
font-size: 16px;
}
.main-header {
padding: 10px;
background-color: #3498db;
color: white;
font-size: 24px;
border-bottom: #1276bb 3px solid; /* #3498db - #222 的结果 */
}
.content-area {
width: 66.66666667%;
float: left;
padding: 20px;
background-color: #f9f9f9;
}
.sidebar {
width: 13.33333333%; /* (100%/3) 是 33.33...% 然后 33.33...% - 20px 变得复杂,结果取决于 strictUnits */
/* 注意:在没有 calc() 的情况下混合 % 和 px 进行减法通常有问题。对于本例,为了健壮性,
最好确保单位兼容或使用 calc()。此处假设 strictUnits: false 进行说明性输出。
更好的方法可能是:width: calc((100% / 3) - @base-spacing); 如果对 calc() 使用转义的话。
为简单起见,不带 calc() 的直接 LESS 输出可能根据设置不太可预测。
让我们简化 sidebar 的 LESS 宽度以便输出更清晰:width: (100% / 3) - 2%; 以获得 2% 的间隙。
然后 sidebar 宽度的 CSS 输出:31.33333333% */
float: right;
padding: 20px;
background-color: #eee;
color: #67c0ef; /* #3498db + #333 的结果 */
}
/* 根据修改后的 .sidebar 宽度在 LESS 中进行的 CSS 修正,以提高清晰度:
.sidebar {
width: 31.33333333%; // 如果 LESS 是:width: (100% / 3) - 2%;
float: right;
padding: 20px;
background-color: #eee;
color: #67c0ef;
} */

关于 calc() 的注意: 对于涉及混合单位(如 % 和 px)且需要在最终 CSS 中保留的复杂计算,通常最好使用 CSS 的 calc() 函数。你可能需要在 LESS 中对其进行转义:width: ~“calc(100% / 3 - 20px)”;。

打开 index.html 将显示一个布局,其中尺寸、内边距、字体大小甚至某些颜色都根据 LESS 文件中定义的运算动态计算。这演示了使用运算创建响应式和主题化设计的强大功能。

LESS 中的转义(~“value”)允许你将字符串按字面值输出到 CSS 中,而 LESS 不会尝试解释或编译它。这对于 LESS 可能无法识别的 CSS 语法、专有浏览器前缀,或者你需要使用在 LESS 中具有特殊含义的字符时是必不可少的。

以下示例演示了如何使用转义来实现非标准 CSS 滤镜(在旧版 IE 中常见)以及输出一个如果处理不当可能与 LESS 语法冲突的 CSS 变量名。

HTML (index.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LESS Escaping</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h1 class="title">Example using Escaping</h1>
<p class="custom-prop-text">This text uses a CSS custom property.</p>
<div class="legacy-element">This element has a legacy Microsoft filter.</div>
</body>
</html>

LESS (style.less):

@custom-property-name: --main-highlight-color;
@legacy-filter-value: "progid:DXImageTransform.Microsoft.Alpha(opacity=50)";
.title {
color: ~"blue"; // 简单的转义,尽管 'blue' 是有效的颜色词。
}
.custom-prop-text {
// 对属性名使用插值,对值使用转义字符串
@{custom-property-name}: ~"#FFD700"; // 金色
color: var(@{custom-property-name});
}
.legacy-element {
// 转义专有滤镜字符串
filter: ~"@{legacy-filter-value}";
// 另一个示例:输出用于 content 的复杂字符串
content: ~"'Chapter ' counter(chapter-number)':'";
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是:

.title {
color: blue;
}
.custom-prop-text {
--main-highlight-color: #FFD700;
color: var(--main-highlight-color);
}
.legacy-element {
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50);
content: 'Chapter ' counter(chapter-number)':';
}

在此示例中,~“blue” 只是输出 blue。真正的威力体现在 @{custom-property-name}: ~“#FFD700”;,其中属性值被转义;以及 filter: ~”@{legacy-filter-value}”;,其中复杂的、潜在非标准的字符串被按原样输出。

在浏览器中查看 index.html 时:

  • .title 将显示蓝色。
  • .custom-prop-text 将显示金色,使用 CSS 自定义属性进行样式化。
  • .legacy-element 将应用指定的 Microsoft 滤镜(如果在支持它的浏览器中查看,如旧版 IE),并且其 content 属性将被设置。
  • 这演示了转义如何确保将特定字符串直接传递到 CSS 输出,这对于兼容性或高级/非标准 CSS 特性至关重要。

LESS 提供了一系列丰富的内置函数,允许你操作值,尤其是颜色、数字和字符串。这些函数通过在样式表中实现动态计算和转换,扩展了 CSS 的能力。

LESS 中的函数通过其名称后跟括号来调用,括号中可以包含参数。示例包括用于将数字转换为百分比的 percentage(),用于舍入数字的 round(),以及各种颜色函数如 lighten(), darken() 和 mix()。

让我们看一个使用几个常见 LESS 函数的示例。

HTML (index.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LESS Functions</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="box">
<p>Styled with LESS functions.</p>
</div>
<button class="btn-primary">Primary Button</button>
</body>
</html>

LESS (style.less):

@base-color: #3498db; // 漂亮的蓝色
@base-font-size: 16px;
@container-width-ratio: 0.8; // 80%
.box {
background-color: lighten(@base-color, 20%); // 将基本颜色提亮 20%
color: darken(@base-color, 30%); // 将基本颜色调暗 30% 用于文本
width: percentage(@container-width-ratio); // 将 0.8 转换为 80%
padding: round(@base-font-size * 0.75); // 舍入 (16px * 0.75 = 12px)
border: 1px solid fade(@base-color, 50%); // 基本颜色,不透明度 50%
}
.btn-primary {
background-color: @base-color;
color: white;
padding: 10px 15px;
border: none;
&:hover {
background-color: saturate(lighten(@base-color, 10%), 10%); // 悬停时使其稍微提亮并更饱和
}
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是:

.box {
background-color: #8bc4ea; /* #3498db 提亮 20% */
color: #1a4c6e; /* #3498db 调暗 30% */
width: 80%;
padding: 12px;
border: 1px solid rgba(52, 152, 219, 0.5); /* #3498db,不透明度 50% */
}
.btn-primary {
background-color: #3498db;
color: white;
padding: 10px 15px;
border: none;
}
.btn-primary:hover {
background-color: #5dade2; /* saturate(lighten(@base-color, 10%), 10%) 的结果 */
}

LESS 提供了种类繁多的函数,可分为:数学函数、字符串函数、列表函数、类型检查函数、颜色定义函数、颜色通道函数、颜色运算函数和颜色混合函数。每个类别都提供了用于操作样式表中不同类型数据的专业工具。

在浏览器中打开 index.html 将显示 .box 元素,其背景颜色被提亮,文本颜色被调暗,宽度和内边距经过计算,并有一个半透明的边框。按钮在悬停时由于颜色操作函数而改变其背景颜色。这演示了 LESS 函数提供的动态样式功能。

LESS 中的命名空间允许你将一组混合集分组到一个共同的标识符下(如 ID 选择器 #utils 或类选择器 .configs)。这有助于组织混合集,防止命名冲突,并创建可重用样式或工具的模块化库。

访问器用于调用或“访问”在命名空间内定义的混合集。你使用大于号(>)或空格来深入命名空间并定位特定的混合集。

让我们为一些常用的排版和盒模型工具创建一个命名空间。

HTML (index.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LESS Namespaces</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<article class="blog-post">
<h1>My Awesome Blog Post</h1>
<p>Some insightful content here...</p>
</article>
<div class="widget">
<h2>Widget Title</h2>
</div>
</body>
</html>

LESS (style.less):

// 使用 ID 选择器定义命名空间(通常首选用于命名空间)
#typography {
.heading-font() {
font-family: 'Georgia', serif;
font-weight: bold;
}
.body-font() {
font-family: 'Arial', sans-serif;
line-height: 1.6;
}
}
// 使用类选择器定义另一个命名空间
.utils {
.clearfix() {
&::after {
content: "";
display: table;
clear: both;
}
}
.border-box() {
box-sizing: border-box;
* {
box-sizing: border-box; // 也应用于子元素
}
}
}
// 应用命名空间的混合集
.blog-post {
#typography > .body-font(); // 从 #typography 命名空间访问混合集
h1 {
#typography .heading-font(); // 另一种访问器语法(空格)
color: #333;
}
}
.widget {
.utils .border-box(); // 从 .utils 命名空间访问混合集
background: #f0f0f0;
padding: 15px;
// .utils > .clearfix(); // 如果 widget 包含浮动元素,也可以使用此方法
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是:

.blog-post {
font-family: 'Arial', sans-serif;
line-height: 1.6;
}
.blog-post h1 {
font-family: 'Georgia', serif;
font-weight: bold;
color: #333;
}
.widget {
box-sizing: border-box;
background: #f0f0f0;
padding: 15px;
}
.widget * {
box-sizing: border-box;
}

关于命名空间和访问器的要点:

Section titled “关于命名空间和访问器的要点:”
  • 命名空间通常使用 ID 选择器(例如,#namespace)或类选择器(例如,.namespace)定义。ID 选择器通常更受青睐,因为除非明确用作选择器,否则它们不会编译到 CSS 中。
  • 要从命名空间调用混合集,请使用 #namespace > .mixin-name() 或 .namespace .mixin-name()(注意空格)。
  • 命名空间可以嵌套,允许更细粒度的组织:#outer > .inner > .mixin()。
  • 此功能对于创建可重用的 LESS 库或工具集而不会污染全局混合集范围非常宝贵。

在浏览器中打开 index.html 将显示使用从各自命名空间调用的混合集进行样式化的博客文章和 widget。这演示了一种干净的方法来组织和应用可重用样式模式。

LESS 中的作用域指的是变量和混合集的可见性和可访问性。LESS 使用词法(或静态)作用域,这意味着首先在本地作用域(使用它们的地方)查找变量。如果在本地找不到,编译器会查找紧密包围的(父)作用域,依此类推,直到全局作用域。

此行为类似于许多编程语言中变量作用域的工作方式。在相同或内部作用域中稍后定义的变量可以覆盖(或遮蔽)在该代码特定部分中较早或在外部作用域中定义的变量。

让我们探讨作用域如何影响变量解析。

HTML (index.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LESS Scope Example</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="outer-block">
<p>Outer block text.</p>
<div class="inner-block">
<p>Inner block text.</p>
<span class="special-span">Special span text.</span>
</div>
</div>
</body>
</html>

LESS (style.less):

@global-color: #3498db; // 全局变量
@padding: 10px;
.outer-block {
@block-color: #2ecc71; // .outer-block 的本地变量
background-color: lighten(@global-color, 30%); // 使用 global-color
padding: @padding; // 使用全局 padding
color: @block-color; // 使用本地 block-color (绿色)
p {
margin-bottom: @padding / 2; // 使用全局 padding
}
.inner-block {
@block-color: #e74c3c; // 重新定义 block-color,本地于 .inner-block (遮蔽外部 .block-color)
@padding: 5px; // 重新定义 padding,本地于 .inner-block (遮蔽全局 padding)
background-color: lighten(@global-color, 40%); // 仍然使用 global-color
padding: @padding; // 使用 inner-block 的本地 padding (5px)
color: @block-color; // 使用 inner-block 的本地 block-color (红色)
.special-span {
// 这将使用来自 .inner-block 的 @block-color (红色)
// 因为它是其作用域链中最接近的定义。
border: 1px solid @block-color;
// 它将使用来自 .inner-block 的 @padding (5px)。
margin: @padding;
}
}
// 回到 .outer-block 作用域
// 如果在此处使用 @block-color,它将是来自 .outer-block 作用域的绿色。
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是:

.outer-block {
background-color: #a9d8f5; /* lighten(#3498db, 30%) */
padding: 10px;
color: #2ecc71;
}
.outer-block p {
margin-bottom: 5px;
}
.outer-block .inner-block {
background-color: #c1e4f7; /* lighten(#3498db, 40%) */
padding: 5px;
color: #e74c3c;
}
.outer-block .inner-block .special-span {
border: 1px solid #e74c3c;
margin: 5px;
}
  • 本地优先: LESS 首先在当前、最具体的范围内查找变量。
  • 延迟加载 / 最后声明获胜(对于同一级别的变量): 如果在完全相同的范围内(例如,全局)定义了多个同名变量,通常在使用之前声明的最后一个变量会生效。然而,对于混合集使用的变量,混合集 调用 或扩展时变量的值通常才是关键,这取决于混合集和变量的处理方式。
  • 遮蔽: 内部作用域中的变量可以在该内部作用域的持续时间内“遮蔽”或隐藏具有相同名称的外部作用域中的变量。
  • 混合集和作用域: 混合集也遵循词法作用域。它们可以访问定义它们的范围内的变量,也可以访问调用它们的范围内的变量(调用者的范围变量可以作为参数传递,如果未被遮蔽,有时也可以直接访问)。

理解作用域对于编写可预测和易于维护的 LESS 代码至关重要,特别是在具有许多变量和嵌套结构的大型项目中。

当查看 index.html 时,.outer-block 将使用全局定义的 @global-color(提亮后)及其自己的 @block-color(绿色)。.inner-block 也将使用 @global-color(提亮更多后),但将使用其自己重新定义的 @block-color(红色)和 @padding(5px)。.inner-block 中的 .special-span 将从 .inner-block 的作用域继承这些值。这演示了不同作用域如何影响最终的 CSS 值。

LESS 支持两种类型的注释,类似于许多编程语言如 JavaScript:

  • 块级注释(CSS 风格): 以 / 开头,以 / 结尾。可以跨多行。块级注释会被保留并出现在编译后的 CSS 输出中。
  • 单行注释(静默注释): 以 // 开头,持续到行尾。单行注释是“静默的”,因为它们会被 LESS 编译器移除,并且不会出现在最终的 CSS 输出中。它们对于在 LESS 文件中添加开发者笔记很有用。

让我们看看这两种类型的注释如何工作。

HTML (index.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LESS Comments Example</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="important-notice">
This is an important notice.
</div>
<p class="regular-text">
This is some regular text.
</p>
</body>
</html>

LESS (style.less):

/*
* 这是一个块级注释。
* 它将出现在编译后的 CSS 文件中。
* 对于许可信息或 CSS 中的部分分隔符很有用。
*/
@primary-color: #3498db;
// 这是一个单行注释。
// 它不会出现在编译后的 CSS 文件中。
// 将它们用于给自己或处理 LESS 代码的其他开发者的笔记。
.important-notice {
color: @primary-color;
font-weight: bold;
/* 另一个块级注释,将被保留 */
padding: 10px;
background-color: #f0f0f0; // 强调样式
}
// 常规文本元素的样式
.regular-text {
color: #333;
line-height: 1.5;
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是:

/*
* 这是一个块级注释。
* 它将出现在编译后的 CSS 文件中。
* 对于许可信息或 CSS 中的部分分隔符很有用。
*/
.important-notice {
color: #3498db;
font-weight: bold;
/* 另一个块级注释,将被保留 */
padding: 10px;
background-color: #f0f0f0;
}
.regular-text {
color: #333;
line-height: 1.5;
}

如你所见,单行注释(//)被移除了,但块级注释(/* … */)保留在输出 CSS 中。

  • 使用块级注释(/* … */)来标记应包含在分发 CSS 中的信息(例如,版权、某个部分的用法说明)。
  • 使用单行注释(// …)来添加开发笔记、复杂逻辑的解释、待办事项,或在 LESS 文件中临时注释掉代码。

打开 index.html 将显示样式化的元素。CSS 文件中是否存在注释不影响浏览器如何渲染样式,但它会影响 LESS 源码和编译后 CSS 的可读性和可维护性。

LESS 中的 @import 指令允许你将 LESS 代码分割成多个更小、更易于管理的文件(通常称为局部文件或模块),然后将它们合并成一个单一的 CSS 输出文件。这对于组织大型项目和提高可重用性至关重要。

LESS 扩展了标准 CSS 的 @import 规则,提供了更多功能和灵活性。默认情况下,LESS 会处理导入的 .less 文件并包含其编译后的 CSS 内容。标准 CSS 的 @import 规则(例如,用于导入外部 CSS 文件或 Google Fonts)通常会原样保留,如果它们具有 .css 扩展名或完整的 URL。

语法:

@import “path/to/your/file.less”; 或 @import “filename”;(如果是 LESS 文件,.less 扩展名是可选的)。

让我们将样式组织到单独的文件中:一个用于变量,一个用于基础样式,一个用于组件样式。

1. 创建 _variables.less(局部文件通常以 _ 开头):

// Variables for colors and fonts
@primary-color: #007bff;
@secondary-color: #6c757d;
@text-color: #333;
@base-font-family: Arial, sans-serif;
@base-font-size: 16px;

2. 创建 _base.less:

// Base styles for HTML elements
body {
font-family: @base-font-family;
font-size: @base-font-size;
color: @text-color;
line-height: 1.6;
margin: 0;
padding: 0;
}
a {
color: @primary-color;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}

3. 创建 _components.less:

// Styles for a button component
.button {
display: inline-block;
padding: 10px 20px;
font-size: @base-font-size;
cursor: pointer;
border: 1px solid transparent;
border-radius: 4px;
}
.button-primary {
.button(); // 类似 Mixin 的调用,包含 .button 的样式
background-color: @primary-color;
color: white;
border-color: @primary-color;
&:hover {
background-color: darken(@primary-color, 10%);
}
}

4. 创建主 LESS 文件 style.less,并导入这些局部文件:

// 导入变量(如果你有一个单独的 _variables.less 文件)
// @import "_variables";
@import "_typography"; // 导入 _typography.less 文件
// 在主文件中定义的样式
.header {
background-color: @secondary-color;
color: white;
padding: 20px;
text-align: center;
}

5. 创建一个 HTML 文件(index.html)来使用这些样式:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LESS Importing Example</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<header class="header">
<h1>Modular Styles with LESS Imports</h1>
</header>
<main style="padding: 20px;">
<p><a href="#">This is a link.</a></p>
<button class="button-primary">Click Me</button>
</main>
</body>
</html>

6. 编译 style.less:

lessc style.less style.css

编译后的 style.css 将包含来自 _variables.less、_base.less、_components.less 和 style.less 的所有样式,并按照导入顺序合并:

/* ... (styles from _variables are used, not output directly) ... */
body {
font-family: Arial, sans-serif;
font-size: 16px;
color: #333;
line-height: 1.6;
margin: 0;
padding: 0;
}
a {
color: #007bff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.button {
display: inline-block;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
border: 1px solid transparent;
border-radius: 4px;
}
.button-primary {
/* Styles from .button() mixin call */
display: inline-block;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
border: 1px solid transparent;
border-radius: 4px;
/* Own styles */
background-color: #007bff;
color: white;
border-color: #007bff;
}
.button-primary:hover {
background-color: #0056b3; /* darken(#007bff, 10%) */
}
.header {
background-color: #6c757d;
color: white;
padding: 20px;
text-align: center;
}

LESS 提供了几种导入选项,通过在 @import 后面的括号中使用关键词来实现,例如 @import (reference) “file.less”;, @import (once) “file.less”;(默认行为), @import (multiple) “file.less”;, @import (less) “file.css”;(视为 LESS 处理), @import (css) “file.less”;(视为 CSS 处理)。

打开 index.html 将显示一个由模块化组织的 LESS 文件进行样式化的页面。这种方法显著提高了 CSS 项目的可维护性和可伸缩性。

LESS 中的变量是编写可重用和可维护 CSS 的基础。它们允许你一次定义一个值,并在整个样式表中重复使用。如果以后需要更改该值(例如,主色调或基本字体大小),只需在一个地方更新即可。

变量使用 @ 符号后跟名称进行声明,并使用冒号(:)赋值,例如:@primary-color: #3498db;。

下表重点介绍了使用 LESS 变量的关键方面:

ID变量用法与描述
1概述与基本用法
变量存储颜色、字体堆栈、尺寸或甚至字符串等值。它们有助于避免重复,并使全局样式更改变得容易。
示例:@base-font-size: 16px; body { font-size: @base-font-size; }
2变量插值
变量可以使用 @{variable-name} 语法插入到字符串、选择器名称、属性名称、URL 和 @import 语句中。
示例:@image-path: “/images”; .icon { background-image: url(”@{image-path}/icon.png”); }
选择器示例:@my-class: special; .@{my-class}-button { color: red; } 编译为 .special-button { color: red; }
3变量名称(命名约定)
变量名称可以包含字母数字字符、连字符(-)和下划线(_)。它们必须以 @ 开头。使用描述性名称是个好习惯(例如,@primary-brand-color 而不是 @c1)。
4作用域与延迟加载
LESS 变量具有词法作用域。它们首先在本地作用域中查找,然后在父作用域中查找。LESS 具有变量的“延迟加载”特性,这意味着变量直到实际使用时才会被评估。对于在同一级别定义的变量,在使用之前的最后一次定义通常优先。这也意味着你可以在引用变量之后定义它们,只要在为该引用生成编译输出之前,它们在相同或可访问的作用域内被定义。
延迟加载示例(同一作用域内最后一次定义获胜):
.element { color: @my-color; } @my-color: blue; @my-color: red;
这通常编译为 .element { color: red; }(取决于确切的编译器版本行为,但通常是有效使用之前的最后一次定义)。
5默认变量(主题化)
虽然 LESS 没有像其他一些预处理器那样特定的“默认变量”语法,但你可以通过重写来实现类似的主题化行为。一种常见模式是定义基础变量,然后允许覆盖。更直接地说,你可以在层叠中稍后重新声明一个变量来更改其值。混合集也可以设计为使用传入的值或在未提供参数时回退到内部默认值。
style.less
// 默认主题变量
@theme-background: #ffffff;
@theme-text-color: #333333;
@theme-primary-color: #007bff;
body {
background-color: @theme-background;
color: @theme-text-color;
}
a {
color: @theme-primary-color;
}
.button-primary {
background-color: @theme-primary-color;
color: white;
padding: 10px 15px;
}
// --- 潜在地,这可以在另一个导入文件中用于深色主题的覆盖 ---
// 要应用深色主题,这些变量可以重新定义:
// @theme-background: #333333;
// @theme-text-color: #f0f0f0;
// @theme-primary-color: #17a2b8;
//
// .dark-theme {
// @theme-background: #222222;
// @theme-text-color: #eeeeee;
// @theme-primary-color: #1abc9c;
// // 重新应用使用这些变量的样式,或者调整结构以使其自然继承
// background-color: @theme-background;
// color: @theme-text-color;
// a { color: @theme-primary-color; }
// .button-primary { background-color: @theme-primary-color; }
// }

这说明了变量如何在 LESS 中构成动态和可维护样式表的骨架。

:extend() 是 LESS 的一个伪类,它允许一个选择器继承另一个选择器的样式,而不会在输出中重复 CSS 属性。相反,它将扩展选择器添加到被扩展规则的选择器列表中。这产生了更高效的 DRY (Don’t Repeat Yourself) CSS。

当你想要将共享完全相同样式块的选择器分组在一起时,它是混合集的一个替代方案,而不是将样式块复制到多个地方。

HTML (extend_basic.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LESS Extend Basic</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="error-message">An error occurred!</div>
<div class="warning-message">Please check your input.</div>
</body>
</html>

LESS (style.less):

.message {
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
font-family: Arial, sans-serif;
}
.error-message {
&:extend(.message); // .error-message 继承 .message 的样式
border-color: red;
background-color: #ffeeee;
color: darkred;
}
.warning-message:extend(.message) { // Extend 也可以直接附加到选择器
border-color: orange;
background-color: #fff8e1;
color: #e65100;
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是:

.message,
.error-message,
.warning-message {
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
font-family: Arial, sans-serif;
}
.error-message {
border-color: red;
background-color: #ffeeee;
color: darkred;
}
.warning-message {
border-color: orange;
background-color: #fff8e1;
color: #e65100;
}

.error-message 和 .warning-message 都将共享 .message 中的通用样式(内边距、外边距、字体),然后应用其特定的样式(边框颜色、背景、文本颜色)。CSS 是高效的,因为通用样式只定义了一次。

:extend() 可以放置在规则集内部(使用 &:extend(…))或直接附加到选择器。它可以扩展一个或多个选择器,用逗号分隔:&:extend(.classA, .classB)。

all 关键词:如果你使用 :extend(.selector all),它将扩展 .selector 的所有实例,包括嵌套在其他选择器内部的实例(例如,.parent .selector)。如果没有 all,它通常只扩展精确的顶层选择器匹配。

LESS (style.less):

.base-style {
font-weight: bold;
}
.another-base {
text-transform: uppercase;
}
nav ul .menu-item {
color: blue;
}
.special-link {
&:extend(.base-style, .another-base);
color: green;
}
.highlighted-menu {
// 这将只扩展精确匹配 `nav ul .menu-item` 的地方
// &:extend(nav ul .menu-item);
// 这将扩展任何以 .menu-item *结尾* 的选择器序列,例如 `nav ul .menu-item`
&:extend(.menu-item all);
background-color: yellow;
}

编译后的 style.css (概念性):

.base-style,
.special-link {
font-weight: bold;
}
.another-base,
.special-link {
text-transform: uppercase;
}
nav ul .menu-item,
nav ul .highlighted-menu { /* 如果 .highlighted-menu 结构与此匹配 */
color: blue;
}
/* 如果 .highlighted-menu 本身是一个类,并且使用 `:extend(.menu-item all)` 进行更精确的说明: */
/* nav ul .menu-item { color: blue; } 将被 nav ul .highlighted-menu 扩展,前提是 .highlighted-menu 也出现在 nav ul 下 */
/* 如果 .highlighted-menu 是一个只进行扩展的顶层类,那么: */
/* nav ul .menu-item, .highlighted-menu { color: blue; } -- 这是简化后的。实际 `all` 的行为取决于选择器匹配。 */
.special-link {
color: green;
}
.highlighted-menu {
background-color: yellow;
}
/* 如果 .highlighted-menu 扩展了 .menu-item all,并且 .menu-item 本身有像 color: blue 这样的样式,
那么 .highlighted-menu 也会获得 color: blue。针对 `color: blue` 的选择器列表将包含 .highlighted-menu。 */
/* 当 `.highlighted-menu` 是同级时,为了 `all` 的清晰性而修正: */
nav ul .menu-item,
.highlighted-menu { /* 假设 .highlighted-menu 可以应用于相似的元素 */
color: blue;
}
  • 语义分组: 将共享基本外观但具有不同修饰符的元素分组(例如,不同类型的警报或按钮)。
  • 减少 CSS 冗余: 避免重复 CSS 属性,与使用混合集达到相同目的相比,可以减小文件大小。
  • 高级类似混合集的行为: 可用于构建比简单属性复制更复杂的样式关系。
  • 混合集(Mixins) 将属性复制到调用选择器中。适用于工具函数以及需要传递参数的情况。
  • 扩展(Extend) 共享选择器。适用于语义关系以及需要避免重复代码块的情况。

下表总结了 :extend 的关键方面:

ID语法/行为与描述
1附加到选择器的 Extend
语法:.my-selector:extend(.extended-selector) { … }。来自 .extended-selector 的样式通过将 .my-selector 添加到 .extended-selector 的规则中来应用于 .my-selector。
2规则集内部的 Extend
语法:.my-selector { &:extend(.extended-selector); … }。效果与上述相同。
3扩展嵌套选择器
&:extend(.parent .child) 将尝试匹配并扩展该特定的嵌套结构。
4精确匹配 vs. all
默认情况下,extend 查找被扩展选择器的精确匹配。all 关键词(例如,&:extend(.child all))使其匹配任何以 .child 结尾的选择器序列。
5扩展多个选择器
&:extend(.sel1, .sel2) 将同时扩展 .sel1 和 .sel2。
6通过 Extend 进行选择器插值
:extend(@{my-variable}) 是可能的,但有局限性;选择器必须在编译时是静态的,extend 才能可靠工作。
7@media 内部的作用域/Extend
Extend 只匹配同一 @media 块内的选择器。它不会扩展其当前媒体上下文之外的选择器。
示例:@media screen { .a:extend(.b); .b { color: red; } } @media print { .b { color: blue; } }
.a 将只获得 color: red,而不是 color: blue。
8重复检测
当多个 extend 定位同一规则时,LESS 会尝试避免创建重复的 CSS 条目。

混合集(Mixins)是 LESS 最强大的特性之一。它们允许你将一个规则集(即混合集)中的一组 CSS 属性嵌入到另一个规则集中。可以将它们视为 CSS 属性的可重用“函数”或“包含”。

这有助于通过一次定义通用样式并在需要的地方应用它们,来保持代码的 DRY (Don’t Repeat Yourself) 特性。

混合集像 CSS 类或 ID 选择器一样定义。要使用混合集,只需在其名称作为 CSS 属性包含在另一个规则集中即可。

HTML (mixins_basic.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LESS Mixins Basic</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="box-alert">This is an alert.</div>
<div class="box-success">This is a success message.</div>
<p class="important-text">Some important text.</p>
</body>
</html>

LESS (style.less):

// 为常见的盒子样式定义一个基本混合集
.common-box-styles() { // 添加 () 使其成为“隐藏”混合集,不作为类输出
padding: 15px;
margin-bottom: 20px;
border: 1px solid #ddd;
border-radius: 4px;
}
// 另一个混合集
.text-emphasis {
font-weight: bold;
font-style: italic;
}
.box-alert {
.common-box-styles(); // 使用混合集
background-color: #f8d7da;
color: #721c24;
border-color: #f5c6cb;
}
.box-success {
.common-box-styles; // 当调用的混合集不是隐藏的时,括号是可选的
background-color: #d4edda;
color: #155724;
border-color: #c3e6cb;
}
.important-text {
.text-emphasis; // 使用 .text-emphasis 混合集
color: #d9534f;
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是:

/* 注意:由于有 (),.common-box-styles() 本身不会作为类输出 */
.text-emphasis {
font-weight: bold;
font-style: italic;
}
.box-alert {
padding: 15px;
margin-bottom: 20px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #f8d7da;
color: #721c24;
border-color: #f5c6cb;
}
.box-success {
padding: 15px;
margin-bottom: 20px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #d4edda;
color: #155724;
border-color: #c3e6cb;
}
.important-text {
font-weight: bold;
font-style: italic;
color: #d9534f;
}
ID混合集用法与描述示例代码片段
1不输出混合集(隐藏混合集)
如果你的混合集定义时名称后面有括号(例如,.my-mixin() { … }),它将不会作为 CSS 类本身输出。它只用作其他规则集引用的源。这是用于工具混合集的常见做法。
.hidden-mixin() { color: blue; } .element { .hidden-mixin(); }
CSS:.element { color: blue; } (.hidden-mixin 未输出)。
2混合集中的选择器
混合集不仅可以包含属性,还可以包含嵌套选择器。当使用混合集时,这些嵌套选择器也会被包含进来,相对于调用选择器。
.parent-mixin() { strong { color: red; } } .my-text { .parent-mixin(); }
CSS:.my-text strong { color: red; }
3命名空间
将相关的混合集分组在一个共同的 ID 或类选择器下,以避免命名冲突并改善组织结构(例如,#utils > .clearfix())。请参见“命名空间和访问器”章节。
#ui-helpers { .border-radius(@radius) { border-radius: @radius; } } .box { #ui-helpers > .border-radius(5px); }
4带守卫的混合集
混合集可以使用 when 关键词附加条件(守卫)。只有当守卫条件评估为 true 时,混合集才会被应用。这允许使用条件逻辑。
.text-color(@c) when (lightness(@c) < 50%) { color: white; } .text-color(@c) when (lightness(@c) >= 50%) { color: black; } .dark-bg { background: #333; .text-color(#333); }
5!important 关键词
如果你在调用混合集时添加 !important(例如,.my-mixin() !important;),该混合集内的所有属性都将输出 !important。
.important-styles() { color: red; font-weight: bold; } .warning { .important-styles() !important; }
CSS:.warning { color: red !important; font-weight: bold !important; }

当调用的混合集定义时没有括号且不是参数化混合集(参见参数化混合集)时,括号 () 是可选的。然而,使用括号(例如,.mixin-name();)是一种常见约定,特别是对于隐藏混合集。

HTML 元素 .box-alert、.box-success 和 .important-text 将通过包含来自 .common-box-styles() 和 .text-emphasis 的属性以及它们自身的特定样式进行样式化。这演示了混合集如何促进代码重用和一致性。

LESS 中的参数化混合集就像编程语言中的函数:它们接受参数,这些参数可以用来定制它们的输出。这使得混合集更加灵活和强大,允许你创建高度可重用的样式模式,以适应不同的需求。

参数在混合集名称后的括号中定义,用逗号(,)或分号(;)分隔。通常首选分号,因为如果你将逗号分隔的列表作为参数传递,逗号可能会产生歧义。

让我们定义一个用于创建可定制宽度、样式和颜色的边框的混合集。

LESS (<code>style.less</code>):
.bordered(@width: 1px; @style: solid; @color: #ccc) {
border-width: @width;
border-style: @style;
border-color: @color;
}
.element1 {
.bordered(2px; dashed; blue); // 提供所有参数
}
.element2 {
.bordered(@color: red); // 只提供颜色,其他使用默认值
}
.element3 {
.bordered(3px; dotted); // 提供宽度和样式,颜色使用默认值
}
.element4 {
.bordered(); // 使用所有默认值
}
编译后的 CSS (<code>style.css</code>):
.element1 {
border-width: 2px;
border-style: dashed;
border-color: blue;
}
.element2 {
border-width: 1px;
border-style: solid;
border-color: red;
}
.element3 {
border-width: 3px;
border-style: dotted;
border-color: #ccc;
}
.element4 {
border-width: 1px;
border-style: solid;
border-color: #ccc;
}
ID特性与描述示例代码片段
1参数的默认值
你可以为参数提供默认值(例如,@width: 1px)。如果在调用混合集时未传递参数,将使用默认值。
.padding(@y: 10px; @x: 20px) { padding: @y @x; } .box { .padding(); }
CSS:.box { padding: 10px 20px; }
2命名参数
你可以通过名称传递参数,这允许你跳过具有默认值的参数或以不同的顺序传递它们。
.text-style(@size: 1em; @weight: normal; @color: #333) { font-size: @size; font-weight: @weight; color: @color; } .title { .text-style(@color: blue; @size: 2em); }
CSS:.title { font-size: 2em; font-weight: normal; color: blue; }
3@arguments 变量
在混合集内部,特殊变量 @arguments 保存传递给混合集的所有参数,作为一个空格分隔的列表。对于 padding 或 margin 等简写属性非常有用。
.shorthand-padding(…) { padding: @arguments; } .box { .shorthand-padding(10px 20px 5px); }
CSS:.box { padding: 10px 20px 5px; } (… 表示它接受可变数量的参数,这些参数都被 @arguments 捕获)
4可变参数 (@rest… 或 …)
你可以通过在参数列表末尾使用 … 来定义接受可变数量参数的混合集(例如,.my-mixin(@a, @b, @rest…))。然后 @rest 变量将保存任何额外的参数作为列表。
.box-shadow(@x; @y; @blur; @color; @rest…) { box-shadow: @x @y @blur @color @rest; } .fancy { .box-shadow(2px; 2px; 5px; #000; inset; 0 0 10px #fff); }
CSS:.fancy { box-shadow: 2px 2px 5px #000 inset, 0 0 10px #fff; } (@rest 捕获 inset, 0 0 10px #fff)
5模式匹配(重载)
你可以定义多个具有相同名称但不同参数(或不同参数数量)的混合集。LESS 将执行与传递的参数匹配的混合集。
.icon(arrow) { background-image: url(‘arrow.png’); } .icon(home) { background-image: url(‘home.png’); } .go-home { .icon(home); }
这更多是关于特定值的匹配,而不是通常按类型/数量进行的重载,但相关。

参数化混合集显著增强了 LESS 的抽象能力,允许创建复杂且高度可配置的样式组件。

虽然 LESS 有专门的函数用于各种运算(颜色、数学、字符串等),但混合集本身可以某种程度上像函数一样工作,尤其是在它们定义变量或通过其作用域隐式返回结果时。它们可以封装逻辑,接受参数,并通过使其中定义的变量可用于调用者的作用域或直接输出 CSS 来有效地“返回”结果。

这个概念更多是关于混合集如何与作用域和变量定义交互,而不是它们像许多编程语言中返回单个、独立值的真正的、第一类函数。

下表重点介绍了赋予混合集函数般特性的方面:

ID方面与描述概念示例
1混合集作用域和变量暴露
在混合集内部定义的变量通常是该混合集的本地变量。然而,如果一个混合集被调用,并且它设置的变量未被参数遮蔽,这些变量有时可以被解释为“输出”或“结果”,从而影响调用作用域或后续规则。
这很复杂,行为可能取决于 LESS 版本和严格性。通常,混合集设置的变量主要用于该混合集的 CSS 输出 内部。直接将值返回到调用作用域进行进一步计算不如使用混合集 应用样式 常见。
@def-var: blue; .caller { @call-var: red; @my-rules: { color: @def-var; border-color: @call-var; }; @my-rules(); }
结果:color blue, border-color red。
2混合集“返回”样式
混合集的主要“返回值”是它生成的 CSS 属性块。参数化混合集允许这些样式是动态的。
.button-style(@bg-color) { background-color: @bg-color; color: white; padding: 10px; } .submit-btn { .button-style(blue); }
“结果”是应用于 .submit-btn 的样式集合。
3混合集为后续使用定义变量(高级)
一个混合集可以定义变量,这些变量随后可以被调用该混合集 之后 定义的其他混合集或规则使用,前提是它们位于可访问的作用域内。这是在工具或主题库中常见的一种更高级模式。
// LESS
.setup-theme(@primary) {
@theme-color: @primary;
@theme-accent: lighten(@primary, 20%);
}

.my-component {
.setup-theme(blue);
background-color: @theme-color; // 使用 ‘blue’
border-color: @theme-accent; // 使用 ‘lighten(blue, 20%)‘
}


在这个概念示例中,.setup-theme “设置”了一些变量,然后 .my-component 使用这些变量。变量 @theme-color 和 @theme-accent 实际上被“返回”到 .my-component 的作用域或其后续规则可访问的作用域。

区分 LESS 的内置函数(如 lighten(), round())和混合集是很重要的。内置函数接受输入并返回单个值供属性使用,而混合集主要用于封装和重用 CSS 规则和属性块。

虽然混合集可以通过参数和内部变量操作数据,但它们主要的“输出”是 CSS 规则。它们“返回值”的概念更多是关于它们如何影响编译上下文和变量作用域,而不是返回单个数据项用于赋值给另一个变量。

对于计算和值转换,优先使用 LESS 内置函数。使用混合集来分组和重用样式声明,这些声明可以通过参数进行定制。

LESS - 将规则集传递给混合集(分离式规则集)

Section titled “LESS - 将规则集传递给混合集(分离式规则集)”

LESS 中的分离式规则集(Detached Ruleset)是一个强大的特性,它允许将一个 CSS 规则块(包括属性、嵌套规则、变量声明,甚至其他混合集调用)存储在一个变量中。然后可以将此变量(即分离式规则集)传递给一个混合集或直接调用,从而有效地将其内容注入到另一个结构中。

这允许创建高度动态和可配置的样式,实现类似于编程中高阶函数或回调的模式。

让我们演示如何定义一个分离式规则集并将其传递给一个混合集,该混合集在特定上下文(例如媒体查询)中应用它。

HTML (detached_ruleset.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LESS Detached Rulesets</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="responsive-box">
This box changes style on larger screens.
</div>
</body>
</html>

LESS (style.less):

// 定义一个接受分离式规则集和媒体查询条件的混合集
.apply-responsive-styles(@ruleset; @condition) {
@media @condition {
@ruleset(); // 在此处调用/执行分离式规则集
}
}
// 定义一个分离式规则集并将其存储在一个变量中
@large-screen-styles: {
// 这是分离式规则集
background-color: lightblue;
font-size: 1.2em;
border: 2px solid darkblue;
.nested-rule {
padding: 10px;
}
};
// 另一个分离式规则集
@small-screen-specifics: {
font-weight: bold;
};
.responsive-box {
padding: 15px;
background-color: #f0f0f0;
border: 1px solid #ccc;
// 使用该混合集应用大屏幕样式
.apply-responsive-styles(@large-screen-styles; ~"(min-width: 768px)");
// 分离式规则集也可以根据需要直接调用(此处未传递给混合集)
// @small-screen-specifics(); // 这会直接将 small-screen-specifics 应用到 .responsive-box
}
// 传递带有变量的规则集的示例
@block-styles: {
@block-color: red;
color: @block-color;
margin: 10px;
.inner {
color: darken(@block-color, 10%);
}
};
.another-box {
@block-styles(); // 直接调用分离式规则集
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是:

.responsive-box {
padding: 15px;
background-color: #f0f0f0;
border: 1px solid #ccc;
}
@media (min-width: 768px) {
.responsive-box {
background-color: lightblue;
font-size: 1.2em;
border: 2px solid darkblue;
}
.responsive-box .nested-rule {
padding: 10px;
}
}
.another-box {
color: red;
margin: 10px;
}
.another-box .inner {
color: #cc0000; /* darken(red, 10%) */
}

当查看 detached_ruleset.html 时:

  • 默认情况下,.responsive-box 具有浅灰色背景。
  • 当视口宽度为 768px 或更大时,来自 @large-screen-styles 的样式(浅蓝色背景、较大字体、深蓝色边框)由于 .apply-responsive-styles 混合集而应用于 .responsive-box。
  • .another-box 将直接应用来自 @block-styles 的样式。

分离式规则集中的变量和混合集基于词法作用域解析。分离式规则集可以访问定义它的地方和调用它的地方的变量。如果在命名冲突时,定义作用域(定义规则集的地方)通常优先。

下表总结了分离式规则集的作用域方面:

ID作用域方面与描述概念示例
1定义和调用者作用域可见性
分离式规则集可以访问定义它的作用域和调用/执行它的作用域中的变量。在分离式规则集 内部 定义的变量是其本地变量,但在规则集展开时使用。
仅仅将分离式规则集赋值给另一个变量(@new-rules: @old-rules;)不会改变其原始作用域或使其访问新的作用域,除非它被实际调用。
作用域主要在定义和调用时确定。
@def-var: blue; .caller { @call-var: red; @my-rules: { color: @def-var; border-color: @call-var; }; @my-rules(); }
结果:color blue, border-color red。
2引用不会修改分离式规则集作用域
Simply assigning a detached ruleset to another variable (@new-rules: @old-rules;) does not change its original scope or give it access to new scopes until it’s actually called.
The scope is primarily determined at definition and call sites.
3通过导入解锁作用域(高级)
如果一个分离式规则集在一个文件中定义并导入(使用特定选项)到另一个文件中,其作用域交互可能会变得更复杂,可能“解锁”或获得导入者的作用域。这是一个高级用例。
通常应用标准的词法作用域规则。
Typically, standard lexical scoping rules apply.

分离式规则集是一个高级特性,对于创建高度可配置的混合集、主题系统或管理复杂条件样式逻辑非常有用。

LESS 中的 @import 指令是一个强大的工具,用于模块化你的样式表。它允许你将 LESS 代码分解成更小、更易于管理的文件(通常称为局部文件或模块),然后将它们合并成一个单一的 CSS 输出文件。这显著提高了大型项目中的组织性、可维护性和可重用性。

LESS 扩展了标准 CSS 的 @import 功能。你几乎可以在 LESS 代码中的任何位置放置 @import 语句,而不仅仅是在顶部。

例如,你可以使用 @import “variables”; 导入文件(对于 LESS 文件,.less 扩展名通常是可选的)。

LESS 根据文件扩展名和某些关键词对 @import 语句进行不同的处理:

  • .less 扩展名: 如果导入的文件具有 .less 扩展名(或没有扩展名,此时假定为 .less),LESS 将处理它并将编译后的 CSS 内容包含在 @import 语句所在的位置。示例:@import “_buttons.less”; 或 @import “_buttons”;
  • .css 扩展名: 如果文件具有 .css 扩展名,LESS 会将其视为标准 CSS 导入。@import 语句本身将保留在编译后的 CSS 输出中。示例:@import “normalize.css”; 在 CSS 中会生成 @import “normalize.css”;。
  • 完整 URL: 如果导入路径是完整 URL(例如,@import url(‘https://fonts.googleapis.com/css?family=Open+Sans’);),它将被视为标准 CSS 导入并保留。
  • 其他扩展名: 如果导入的文件扩展名不是 .css 或 .less(例如,旧示例中的 .php,或 .txt),LESS 仍然会尝试将其处理为 LESS 文件。这通常不推荐;LESS 文件请使用 .less。
  • 导入选项: 关键词如 (less), (css), (reference), (inline) 可以强制 LESS 以特定方式处理导入的文件,覆盖基于扩展名的默认行为(参见“导入选项”章节)。
示例,展示扩展名如何影响导入:
@import "theme-variables"; // 导入 theme-variables.less 并处理
@import "base-styles.less"; // 导入 base-styles.less 并处理
@import "external-lib.css"; // 在输出中保留为 @import "external-lib.css";
@import (less) "my-styles.css"; // 将 my-styles.css 视为 LESS 文件并处理
@import (css) "component.less"; // 输出 @import "component.less"; (视为 CSS 导入)

让我们创建一个简单的项目结构,其中包含导入的文件。

HTML (index.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Import Directives</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<header class="main-header">Header Content</header>
<p class="main-text">Welcome to our website using modular LESS styles!</p>
</body>
</html>

创建一个局部文件,例如 _typography.less:

@base-font-size: 16px;
@heading-font-family: 'Georgia', serif;
body {
font-size: @base-font-size;
}
.main-header {
font-family: @heading-font-family;
font-size: @base-font-size * 1.8;
}

现在,创建主要的 style.less 文件并导入该局部文件:

// 导入变量(如果你有一个单独的 _variables.less 文件)
// @import "_variables";
@import "_typography"; // 导入 _typography.less 文件
// 在主文件中定义的样式
.main-header {
background-color: #333;
color: white;
padding: 20px;
}
.main-text {
color: #555;
margin-top: 15px;
font-size: @base-font-size * 1.1; // 使用来自 _typography.less 的 @base-font-size 变量
}

_typography.less 文件的内容将被处理并包含在 style.less 中。在 _typography.less 中定义的变量(如 @base-font-size)可供 style.less 中的后续规则使用。

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将合并这两个文件:

body {
font-size: 16px;
}
.main-header {
font-family: 'Georgia', serif;
font-size: 28.8px; /* 16px * 1.8 */
background-color: #333;
color: white;
padding: 20px;
}
.main-text {
color: #555;
margin-top: 15px;
font-size: 17.6px; /* 16px * 1.1 */
}

在浏览器中打开 index.html 将显示按照来自 _typography.less 和 style.less 的组合规则进行样式化的页面,演示了使用 LESS 导入进行模块化 CSS 开发的强大功能。

LESS 增强了 @import 指令,提供了几个控制文件如何导入和处理的选项。这些选项在 @import 关键词后的括号中指定,文件路径之前,例如:@import (option) “filename”;。

这些选项提供了对导入过程的细粒度控制,允许实现高级用例,如仅引用样式而不输出它们、内联 CSS 或确保文件仅导入一次。

下表列出了可用的导入选项:

ID导入选项与描述解释/示例结果
1reference (引用)
@import (reference) “library.less”;
导入 LESS 文件但 不 直接输出其 CSS。引用文件中的样式只有在导入文件中通过 :extend 或作为混合集调用时才输出。这对于导入工具库(如混合集集合或占位符选择器)非常有用,而无需将其整个代码库添加到你的 CSS 中,除非明确使用。
如果 library.less 包含 .my-mixin { color: blue; },并且你的主文件执行 .element { .my-mixin(); },只有那时 color: blue; 才会成为 .element 输出的一部分。.my-mixin 本身不会被输出,除非它也定义时没有 () 并用作类。
2inline (内联)
@import (inline) “external.css”;
直接将指定文件的内容包含到输出 CSS 中,不 进行任何 LESS 处理。导入文件的内容被视为纯 CSS。这对于嵌入你不想让 LESS 干预的第三方 CSS 非常有用。
如果 external.css 包含 body { margin: 0; },则此精确的 CSS 将被放置在你的输出文件中。
3less (强制为 LESS)
@import (less) “styles.txt”;
强制 LESS 将导入的文件视为 LESS 文件并处理它,无论其实际的文件扩展名如何。这对于在非标准扩展名的文件中包含 LESS 代码时很有用。
如果 styles.txt 包含 @color: red; .box { color: @color; },它将被处理为 LESS,输出 .box { color: red; }。
4css (强制为 CSS)
@import (css) “variables.less”;
强制 LESS 将导入的文件视为标准 CSS 文件。@import 语句本身将保留在输出 CSS 中,而不是 LESS 处理文件内容。
@import (css) “variables.less”; 将在最终 CSS 文件中输出 @import “variables.less”;。
5once (仅一次)
@import (once) “theme.less”; (这是默认行为)。
确保文件只被导入和处理一次,即使在你的项目中被导入多次。这防止了重复的 CSS 输出和冗余的处理。
如果 theme.less 在多个文件中被导入,其样式将只在最终编译的 CSS 中出现一次。
6multiple (多次)
@import (multiple) “mixins.less”;
允许文件被多次导入和处理,如果它被多次引用。这很少需要,但在你故意想重复 LESS 文件的输出的特定场景中可能有用,也许是不同的变量上下文(尽管这很高级,通常最好通过参数化混合集处理)。
谨慎使用,因为它如果管理不当可能导致 CSS 臃肿。
Use with caution as it can lead to bloated CSS if not managed carefully.
7optional (可选)
@import (optional) “custom-overrides.less”;
允许即使找不到要导入的文件,编译也能继续进行。如果文件存在,则导入;如果不存在,LESS 会继续编译而不会出错。这对于主题定制或可能并非总是存在的可选模块非常有用。
如果 custom-overrides.less 不存在,不会抛出错误,编译继续。如果存在,则正常导入。

可以使用逗号分隔多个关键词,例如:

@import (reference, optional) "ui-kit-variables.less";

这将导入 ui-kit-variables.less 仅供引用(除非使用,否则其样式不会输出),并且如果文件不存在,编译将继续而不会出错。

理解并有效使用这些导入选项可以显著提高 LESS 项目的结构、效率和灵活性。

LESS 中的混合集守卫(Mixin Guards)允许你定义混合集何时应该被应用的条件。它们就像你混合集的“if”语句,使得你可以在样式表中实现条件逻辑。一个带有守卫的混合集只有在其守卫条件评估为 true 时才会产生输出。

守卫使用 when 关键词后跟括号中的条件来指定,放在混合集声明之后。你可以为同一混合集的不同版本设置多个守卫条件(基于条件的重载),或者为一个混合集设置多个条件(使用 and, or, not)。

守卫条件可以使用:

  • 比较运算符:>, >=, =(用于相等判断,不是赋值), =<, <。
  • 逻辑运算符:and, or, not()。
  • 类型检查函数:iscolor(), isnumber(), isstring(), iskeyword(), isurl() 等。
  • default() 函数,它在没有其他带守卫的混合集匹配时充当“else”条件。

让我们创建一些混合集,它们根据颜色的亮度或特定关键词应用不同的样式。

HTML (mixin_guards.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Mixin Guards</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="light-background-box">Light Background</div>
<div class="dark-background-box">Dark Background</div>
<div class="button-primary">Primary Button</div>
<div class="button-secondary">Secondary Button</div>
</body>
</html>

LESS (style.less):

// 根据背景亮度设置文本颜色的混合集
.adaptive-text-color(@bg-color) when (lightness(@bg-color) >= 50%) {
color: #333; // 浅色背景使用深色文本
}
.adaptive-text-color(@bg-color) when (lightness(@bg-color) < 50%) {
color: #fff; // 深色背景使用浅色文本
}
// 根据类型设置按钮样式的混合集
.button-style(@type) when (@type = primary) {
background-color: blue;
border: 1px solid darkblue;
}
.button-style(@type) when (@type = secondary) {
background-color: grey;
border: 1px solid dimgrey;
}
// 默认或通用按钮样式(也可以使用 default() 守卫)
.button-style(@type) {
padding: 10px 15px;
display: inline-block;
text-align: center;
// 这确保了任何按钮类型的文本颜色都是自适应的
.adaptive-text-color(extract(lookup("background-color"), 1)); // 有点高级:查找其自身的背景颜色
// 更简单:传递背景颜色:.adaptive-text-color(blue) 用于 primary
}
.light-background-box {
background-color: #f0f0f0; // 浅色背景
padding: 20px;
.adaptive-text-color(#f0f0f0);
}
.dark-background-box {
background-color: #2c3e50; // 深色背景
padding: 20px;
.adaptive-text-color(#2c3e50);
}
.button-primary {
.button-style(primary);
// 为了让按钮的文本颜色自适应更简单:
.adaptive-text-color(blue); // 明确传递已知的背景颜色
}
.button-secondary {
.button-style(secondary);
.adaptive-text-color(grey);
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是:

.button-style {
/* 这个来自 .button-style(@type) 的通用部分可能会出现,如果调用时没有匹配的守卫,
或者如果匹配了带守卫的版本,它的属性会被合并。
这里的 lookup() 函数用法复杂,示例需要细化。
为清晰起见,假设通用样式总是输出的。 */
padding: 10px 15px;
display: inline-block;
text-align: center;
}
.light-background-box {
background-color: #f0f0f0;
padding: 20px;
color: #333; /* 由于浅色 #f0f0f0,来自 .adaptive-text-color */
}
.dark-background-box {
background-color: #2c3e50;
padding: 20px;
color: #fff; /* 由于深色 #2c3e50,来自 .adaptive-text-color */
}
.button-primary {
/* 通用按钮样式 */
padding: 10px 15px;
display: inline-block;
text-align: center;
/* 来自 .button-style(primary) 的样式 */
background-color: blue;
border: 1px solid darkblue;
/* 文本颜色 */
color: #fff; /* 来自 .adaptive-text-color(blue) */
}
.button-secondary {
/* 通用按钮样式 */
padding: 10px 15px;
display: inline-block;
text-align: center;
/* 来自 .button-style(secondary) 的样式 */
background-color: grey;
border: 1px solid dimgrey;
/* 文本颜色 */
color: #333; /* 来自 .adaptive-text-color(grey) */
}

注意:原示例中用于 .button-style(@type) 的 lookup() 函数是用于检查先前设置属性的高级特性,可能并不总是直观。更常见的按钮文本自适应模式是在每个特定按钮样式内部,用该按钮的背景颜色显式调用 .adaptive-text-color(),如修正后的 .button-primary 和 .button-secondary 所示。

ID类型与描述
1守卫比较运算符
使用 <, >, <=, >=, =(相等)来比较数字、字符串、关键词等。示例:when (@value > 10), when (@name = “example”)。
2守卫逻辑运算符
使用 and, or 组合条件。使用 not() 否定条件。示例:when (@value > 10) and (@name = “example”), when not (@value = 0)。
3类型检查函数
在守卫中使用函数,如 iscolor(), isnumber(), isstring(), iskeyword(), isurl(), isunit(@val, unit)。示例:when (iscolor(@param)), when (isnumber(@param)) and (@param > 0)。
4default() 函数
守卫中的 default() 函数在没有其他混合集(同名)的条件评估为 true 时,评估为 true。它充当“else”或回退情况。

HTML 元素将根据条件进行样式化。.light-background-box 将获得深色文本,而 .dark-background-box 将获得浅色文本。.button-primary 和 .button-secondary 将根据传递给 .button-style() 的类型具有不同的样式,其文本颜色也将自适应。这展示了守卫在创建灵活和智能混合集方面的强大功能。

LESS 中的 CSS 守卫(或选择器守卫)允许你根据守卫表达式有条件地应用整个样式块(规则集)。与控制混合集内容是否输出的混合集守卫不同,CSS 守卫控制整个 CSS 规则集(包括其选择器)是否输出。

它们使用 when 关键词直接应用于选择器。如果守卫条件为 true,则整个规则集(选择器及其属性)包含在编译后的 CSS 中。这对于仅在某些条件(通常基于 LESS 变量值)下应用样式非常有用。

此功能有时与父选择器 & 结合使用,以创建样式的条件变体。

让我们定义一个全局主题变量,并且仅当主题设置为 ‘dark’ 时应用某些样式。

HTML (css_guards.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LESS CSS Guards</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">
<h1>Welcome to the Page</h1>
<p>This content might look different based on the theme.</p>
<button class="action-button">Click Me</button>
</div>
</body>
</html>

LESS (style.less):

@theme: dark; // 可能的值: 'light', 'dark'
@enable-special-feature: true;
.container {
padding: 20px;
background-color: #f0f0f0; // 默认浅色背景
color: #333; // 默认深色文本
// CSS 守卫:仅当 @theme 为 'dark' 时应用这些样式
& when (@theme = dark) {
background-color: #2c3e50; // 深色主题使用深色背景
color: #ecf0f1; // 深色主题使用浅色文本
h1 {
border-bottom: 1px solid #ecf0f1;
}
}
}
.action-button when (@enable-special-feature = true) and (@theme = dark) {
// 只有当特殊功能启用且主题为 dark 时,此规则才输出
background-color: #1abc9c; // 深色主题特殊功能的青色按钮
color: white;
border: none;
padding: 10px 20px;
}
// 另一个示例:如果条件满足,则普遍应用样式
body when (@theme = dark) {
filter: invert(5%); // 对整个 body 的深色主题进行微妙的反转效果
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是(假设如上所示设置了 @theme: dark; 和 @enable-special-feature: true;):

.container {
padding: 20px;
background-color: #f0f0f0;
color: #333;
}
/* 来自第一个 CSS 守卫的样式,因为 @theme = dark */
.container {
background-color: #2c3e50;
color: #ecf0f1;
}
.container h1 {
border-bottom: 1px solid #ecf0f1;
}
/* 来自第二个 CSS 守卫的样式,因为条件满足 */
.action-button {
background-color: #1abc9c;
color: white;
border: none;
padding: 10px 20px;
}
/* 来自第三个 CSS 守卫的样式 */
body {
filter: invert(5%);
}

例如,如果 @theme 在 style.less 中设置为 ‘light’,那么针对 .container(深色主题版本)、.action-button 和 body 的带守卫规则集将不会出现在编译后的 CSS 中。

  • CSS 守卫控制整个规则集的输出。
  • 它们使用与混合集守卫相同的 when 关键词和条件逻辑。
  • 这对于主题化、功能标记或任何需要仅在满足某些条件(通常基于 LESS 变量)时才应用 CSS 块的情况非常有用。

当设置了 @theme: dark; 和 @enable-special-feature: true; 时,.container 将具有深色背景和浅色文本,其中的 h1 将有浅色边框,.action-button 将具有其特殊的深色主题样式,并且整个 body 将具有微妙的反转滤镜。如果变量不同,这些特定的样式将不会出现,这演示了 CSS 守卫控制条件输出的能力。

LESS 没有像传统编程语言中那样的专用循环构造(如 for 或 while)。但是,可以通过结合使用递归混合集、守卫表达式和(可选的)模式匹配来实现循环。

递归混合集是指调用自身的混合集。守卫条件用于在满足特定条件时终止递归(例如,计数器达到零或限制)。

这项技术对于生成重复的 CSS 模式非常强大,例如网格列、用于间距的工具类或序列化的主题元素。

让我们创建一个循环来生成一系列宽度工具类(例如,.width-25 表示 25%,.width-50 表示 50%)。

HTML (loops_example.html) - 用于演示用法:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LESS Loops Example</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="width-25 item">25% Width</div>
<div class="width-50 item">50% Width</div>
<div class="width-75 item">75% Width</div>
<div class="width-100 item">100% Width</div>
<div class="spacer-3 item">Spacer 3 (margin-top: 30px)</div>
</body>
</html>

LESS (style.less):

// 循环生成宽度类:.width-N,其中 N 是百分比
// 参数:@iterations - 总步数,@index - 当前步数,@step-size - 每步的百分比
.generate-width-classes(@iterations; @index: 1; @step-size: 25) when (@index =< @iterations) {
@percentage-value: @index * @step-size;
.width-@{percentage-value} { // 使用变量插值作为类名
width: unit(@percentage-value, %);
}
// 下一次迭代的递归调用
.generate-width-classes(@iterations; (@index + 1); @step-size);
}
// 调用循环生成 4 个类 (25%, 50%, 75%, 100%)
.generate-width-classes(4; 1; 25);
// 循环生成间隔类:.spacer-N
.generate-spacers(@n; @i: 1; @base-margin: 10px) when (@i =< @n) {
.spacer-@{i} {
margin-top: @base-margin * @i;
}
.generate-spacers(@n; (@i + 1); @base-margin); // 递归调用
}
// 生成 5 个间隔类 (.spacer-1 到 .spacer-5)
.generate-spacers(5);
// HTML 中用于可见性的基础样式
.item {
background-color: #f0f0f0;
padding: 10px;
margin-bottom: 5px;
border: 1px solid #ccc;
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将包含:

.width-25 {
width: 25%;
}
.width-50 {
width: 50%;
}
.width-75 {
width: 75%;
}
.width-100 {
width: 100%;
}
.spacer-1 {
margin-top: 10px;
}
.spacer-2 {
margin-top: 20px;
}
.spacer-3 {
margin-top: 30px;
}
.spacer-4 {
margin-top: 40px;
}
.spacer-5 {
margin-top: 50px;
}
.item {
background-color: #f0f0f0;
padding: 10px;
margin-bottom: 5px;
border: 1px solid #ccc;
}
  • .generate-width-classes 混合集接受总迭代次数、当前索引和步长的参数。
  • 守卫条件 when (@index =< @iterations) 确保混合集仅在当前索引在所需范围内执行。
  • 在混合集内部,生成一个类(例如,.width-25)及其对应的 CSS 属性(例如,width: 25%;)。
  • 然后混合集通过递增索引(@index + 1)调用自身,继续循环。
  • 当 @index 超过 @iterations 时,守卫条件变为 false,递归停止。

在浏览器中打开 loops_example.html 将显示应用了生成的宽度和间隔类样式后的 div。这演示了 LESS 循环如何自动化创建工具类系统或其他重复的 CSS 模式,节省时间并减少手动编码。

LESS 中的合并(Merge)功能允许你将来自多个声明的相同属性的值聚合成一个单一的、逗号分隔或空格分隔的列表。这对于可以接受多个值的 CSS 属性特别有用,例如 background、transform、box-shadow 或 font-family。

要使用合并功能,你需要在属性名后附加 +(用于逗号分隔)或 +_(用于空格分隔)。

下表描述了两种类型的合并操作:

ID合并类型与描述常见用例
1逗号 (+)
将新的属性值附加到现有列表中,用逗号分隔。如果属性尚不存在,则创建它。
例如用于 box-shadow 或多个背景。
2空格 (+_)
将新的属性值附加到现有列表中,用空格分隔。如果属性尚不存在,则创建它。
例如用于 transform 函数或类列表(尽管类列表通常在 HTML 中处理)。

示例:使用合并功能处理 box-shadow 和 transform

Section titled “示例:使用合并功能处理 box-shadow 和 transform”

HTML (merge_example.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LESS Merge Example</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="layered-shadow-box">Layered Shadows</div>
<div class="transformed-element">Transformed</div>
</body>
</html>

LESS (style.less):

.base-effects() {
box-shadow+: 0 0 5px rgba(0,0,0,0.2); // 逗号分隔合并
transform+_: scale(1); // 空格分隔合并
}
.extra-depth() {
box-shadow+: 5px 5px 10px rgba(0,0,0,0.3) inset; // 添加另一个阴影
}
.rotate-effect() {
transform+_: rotate(10deg); // 添加一个旋转
}
.layered-shadow-box {
.base-effects();
.extra-depth();
width: 200px;
height: 100px;
padding: 20px;
background-color: #f0f0f0;
margin: 20px;
}
.transformed-element {
.base-effects();
.rotate-effect();
transform+_: translateX(20px); // 添加另一个 transform
width: 150px;
height: 75px;
padding: 15px;
background-color: #e0e0e0;
margin: 20px;
text-align: center;
}

编译 style.less 到 style.css:

lessc style.less style.css

编译后的 style.css 将是:

.layered-shadow-box {
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2), 5px 5px 10px rgba(0, 0, 0, 0.3) inset;
transform: scale(1);
width: 200px;
height: 100px;
padding: 20px;
background-color: #f0f0f0;
margin: 20px;
}
.transformed-element {
transform: scale(1) rotate(10deg) translateX(20px);
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
width: 150px;
height: 75px;
padding: 15px;
background-color: #e0e0e0;
margin: 20px;
text-align: center;
}
  • property+: value; 使用逗号附加 value。
  • property+_: value; 使用空格附加 value。
  • 此功能在需要逐步构建复杂的多值属性时非常有用,通常通过不同的混合集或样式层来实现。
  • 当你只想向多值属性添加内容而不覆盖之前的部分时,它避免了覆盖问题。

在浏览器中打开 merge_example.html 将显示:

  • .layered-shadow-box 将同时应用两个盒子阴影(一个外阴影,一个内阴影)。
  • .transformed-element 将依次应用所有三个 transform(缩放,然后旋转,然后平移)。

这演示了合并功能如何帮助从多个来源组合复杂的 CSS 属性。