主题
Less 语法(Day19 3/3)
本页对应 Day19_PC项目&Less,共 5 段视频,约 59 分钟。
学习目标
- 能够使用
@import导入.less与.css文件,并通过编译结果说明二者在内容合并与原样输出上的差异。 - 能够编写 Less 嵌套规则,正确生成后代、子元素、相邻兄弟、通用兄弟选择器,并使用
&生成交集选择器、伪类和伪元素。 - 能够将混合与嵌套结合使用,编写并调用带嵌套结构的混合(如清除浮动),并说明混合内变量与混合在常见开发场景中的使用方式。
- 能够使用
+、-、*、/进行 Less 运算,正确使用括号处理除法,并说明运算结果的单位选择规则。 - 能够使用
percentage()、mod()、lighten()、darken()等 Less 函数完成百分比计算、取余和颜色亮度调整,并验证编译结果。
知识点
Less 导入:先理解 CSS @import 与 Less @import 的差异
为什么需要:项目里常把变量、重置样式、混合拆成多个文件,如果每个页面都手工复制,维护成本高。怎么想:先看 CSS 本身也支持 @import,再看 Less 导入 .less 文件时会把内容合并进最终 CSS。怎么做:课堂先写 index.css 导入 reset.css 做对照,再新建 index.less:
less
@import "reset.css";
@import "variables.less";导入 Less 文件时可省略 .less,Less 会自动补扩展名:
less
@import "variables";实际结构常是:variables.less 放变量,reset.less 放重置样式,index.less 作为入口文件统一导入,只编译 index.less,其他零碎 Less 文件不单独编译。易错点:导入 .css 时,Less 会把 @import 原样编译到 CSS 中;导入 .less 时,才会把目标文件内容拿过来合并。被导入的模块文件扩展名应是 .less,否则不会按 Less 内容合并。
Less 嵌套:层级选择器、& 与媒体查询
为什么需要:CSS 里写 .container .item .active 容易重复写父级,结构深时难找。怎么想:Less 允许在选择器内部继续写子选择器,编译时生成层级选择器。怎么做:
less
.container {
.item {
color: red;
> .active { color: blue; }
+ .content { color: green; }
~ div { background: #900; }
}
}它会编译出后代、子代 >、相邻 +、兄弟 ~ 等结构。& 用来取消层级、做交集或拼伪类:
less
.item {
&.active { color: red; }
&:hover { color: blue; }
&::after { content: ""; }
}媒体查询也可嵌在选择器里,编译后会自动补上选择器:
less
.container {
width: 100%;
@media (min-width: 768px) {
width: 80%;
}
}易错点:不加 & 时,.item { :hover {} } 会变成后代选择器;加了 & 才是 .item:hover。媒体查询嵌套只是写法简化,浏览器最终认识的仍是普通媒体查询结构。
混合与嵌套结合:作用域、变量提升与清除浮动
为什么需要:混合像“自定义函数”,可复用一段样式;嵌套让混合内部也能写层级。怎么想:先定义混合,再在选择器中调用;混合内变量和内部混合的使用范围要实测。怎么做:
less
.center-books(@w: 500px) {
width: @w;
&:after {
display: block;
clear: both;
}
}
.wrapper {
.center-books();
}课堂还演示了清除浮动混合:
less
.clearfix() {
&:after {
display: block;
clear: both;
}
}易错点:转写稿中先以为混合内变量外部不能用,后来发现是变量名写错;当前规则下变量可提升,不必过度纠结复杂作用域。混合内再定义混合时,若外层没有调用父混合,内部混合不能直接用;调用父混合后才可用。实际开发按“变量单独文件、混合单独文件、入口统一导入”的规范写,基本不受这些边界影响。
Less 运算符:加减乘除、单位与括号
为什么需要:宽度、间距常需计算,如一行 6 个元素。怎么想:Less 支持 + - * /,但单位规则和除法写法要验证。怎么做:
less
.box {
width: 10 + 10px; // 20px
height: 80% + 10%; // 90%
margin: (100px / 2); // 50px
padding: mod(100px, 6);// 4px
}两个操作数都有单位时,结果取第一个操作数的单位;只有一个有单位时用该单位;都没有单位则结果无单位。相同属性相同值会被合并。易错点:除法必须用小括号包起来,否则斜杠会被当成属性值的一部分,因为 background、font、border-radius 等 CSS 值里本来就有斜杠。% 不支持取余运算,要用 mod() 函数。
Less 函数:百分比、取余与颜色明暗
为什么需要:有些计算用运算符不方便,Less 自带函数可做纯计算。怎么想:函数很多,不必全记,掌握常用几个即可。怎么做:
less
.col {
width: percentage(1 / 6); // 约 16.666%
margin: mod(100px, 6); // 4px
background: lighten(#900, 10%);
color: darken(#900, 20%);
}percentage() 会自动拼百分号;mod() 补足取余;lighten()、darken() 调整颜色明暗。易错点:Less 函数不是自定义混合,不生成样式,主要用于计算;大量数学、三角函数和颜色函数实际写样式很少用,不要为了记函数而记函数,按需查文档即可。
课堂画面





代码示例
示例一:Less 导入(入口文件 + 变量文件 + 重置样式)
文件结构
demo/
├── index.html
├── index.less ← 入口文件(只编译它)
├── variables.less ← 变量文件(不单独编译)
└── reset.less ← 重置样式表(不单独编译)index.html
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Less 导入</title>
<!-- 注意:rel 必须是 stylesheet/less -->
<link rel="stylesheet/less" href="./index.less">
<script src="https://cdn.jsdelivr.net/npm/less@4"></script>
</head>
<body>
<h1>导入</h1>
<p>这是一段文字</p>
</body>
</html>variables.less
less
@master-red: #f00;
@base-font: 16px;reset.less
less
* {
margin: 0;
padding: 0;
}index.less(入口文件)
less
// 导入 .less 文件:扩展名可以省略
@import "./reset";
@import "./variables";
h1 {
color: @master-red;
}
p {
font-size: @base-font;
}关键行与易错点
@import "./reset";省略.less后 Less 会自动补上,等价于@import "./reset.less";。- 导入
.less与导入.css结果完全不同:导入.less时,被导入文件的内容会被合并进来,最终产物里只有一份 CSS;导入.css(如@import "theme.css";)时,Less 会原样输出这条@import语句,内容不会被合并——所以拆分的零碎文件扩展名必须是.less。 - 拆分后只需要编译
index.less这一个入口文件,reset.less、variables.less不需要单独编译出同名 CSS。 - 浏览器端用 less.js 编译
@import会发起额外请求,file://打开会跨域失败,必须用本地 http 服务(如 VSCode Live Server)打开。
示例二:嵌套、& 符号与媒体查询嵌套
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Less 嵌套</title>
<style type="text/less">
@master-red: #f00;
.container {
width: 600px;
margin: 0 auto;
.item {
line-height: 40px;
font-size: 14px;
/* & 取消层级:生成 .container .item.active */
&.active {
color: @master-red;
}
/* 生成 .container .item:hover */
&:hover {
background-color: #eee;
}
/* 伪元素紧跟:.container .item::after */
&::after {
content: " →";
color: #999;
}
/* 子元素选择器 */
> .title {
font-weight: bold;
}
/* 相邻兄弟选择器 */
+ .item {
border-top: 1px solid #ccc;
}
/* 通用兄弟选择器 */
~ .desc {
color: #666;
}
}
/* 媒体查询嵌套:不用再重复写 .container 选择器 */
@media (min-width: 768px) {
width: 750px;
}
}
</style>
<script src="https://cdn.jsdelivr.net/npm/less@4"></script>
</head>
<body>
<div class="container">
<div class="item active"><span class="title">标题一</span></div>
<div class="item">标题二</div>
<div class="desc">描述文字</div>
</div>
</body>
</html>关键行与易错点
- 嵌套默认生成后代选择器(带空格):
.container .item;写> .title、+ .item、~ .desc时 Less 会保留这些组合符,生成.container .item > .title等层级结构选择器。 &的作用是取消层级、拼接成同一层:&.active→.item.active(交集选择器,中间无空格);&:hover→.item:hover;&::after→.item::after。- 最容易错:写成
.active { }(不加&)会变成后代选择器.item .active,与&.active的效果完全不同。 - 媒体查询写在选择器内部时,Less 会自动把当前选择器包进
@media里,编译成浏览器认识的@media (min-width: 768px) { .container { width: 750px; } },省去重复写选择器的麻烦。
示例三:混合、运算符与内置函数
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Less 混合 / 运算 / 函数</title>
<style type="text/less">
@master-red: #f00;
/* 混合:清除浮动,内部用 & 接伪元素 */
.clearfix() {
&::after {
display: block;
clear: both;
content: "";
}
}
.wrapper {
.clearfix(); /* 带括号调用,不输出 .clearfix 本身 */
border: 1px solid #ccc;
.box {
float: left;
width: 100px;
height: 50px;
background-color: @master-red;
}
}
.calc {
width: 10 + 10px; /* 20px 只有一个带单位,取该单位 */
height: 56px + 10; /* 66px 同上 */
margin-left: 1em + 78px; /* 79em 都带单位,取前一个的单位 */
padding-left: (100px / 2); /* 50px 除法必须加括号 */
padding-top: mod(100px, 6);/* 4px 取余用 mod() 函数 */
}
.fn {
width: percentage((1 / 6)); /* 16.66666667% */
background-color: lighten(#900, 10%); /* #cc0000 调亮 */
color: darken(#900, 20%); /* #330000 调暗 */
}
</style>
<script src="https://cdn.jsdelivr.net/npm/less@4"></script>
</head>
<body>
<div class="wrapper"><div class="box">box</div></div>
<div class="calc">calc</div>
<div class="fn">fn</div>
</body>
</html>关键行与易错点
.clearfix()定义时带括号是混合,调用.clearfix();只把内容拷进.wrapper;若定义时不带括号写成.clearfix { },它就是一个普通类,编译后会额外输出一份.clearfix样式。- 混合里写
&::after,调用时&会替换成调用者(.wrapper),生成.wrapper::after;如果写成::after而不加&,会变成后代选择器.wrapper ::after,清除浮动就失效了。 - 运算单位规则:两个操作数只有一个带单位→ 用那个单位;都带单位→ 用前一个的单位(
1em + 78px=79em,没有谁优先级更高,只看先后)。 - 除法必须加小括号
(100px / 2),否则 Less 会把/当成属性值的一部分原样输出——因为 CSS 本身在background、font、border-radius等复合属性里就用斜杠做分隔,Less 无法区分。 - Less 不支持
%取余运算,要用mod(100px, 6)函数。 percentage((1/6))内层除法也要括号;lighten()/darken()的第二个参数是百分比,直接调亮/调暗颜色,省去自己算色值。
常见错误
现象:在 Less 中写
@import "reset.css";,期望把 CSS 内容合并进来,结果编译后仍是导入语句。
原因:导入.css文件时按 CSS 导入原样保留,不会像 Less 模块一样内联。
修法:需要内联和参与 Less 编译时改为.less文件;确实要保留 CSS 导入语义时再使用.css。现象:嵌套里写
.item { :hover { ... } },生成的是后代选择器,不是元素自身 hover。
原因:缺少&,嵌套默认按层级/后代关系拼接。
修法:伪类、伪元素、属性选择器、交集选择器需要紧贴时写成&:hover、&::after、&.active。现象:
width: 100px / 2;没有计算出结果,斜杠被原样保留。
原因:CSS 属性值中斜杠有合法语义,Less 新版不会无条件把/当除法。
修法:除法用括号明确计算,如width: (100px / 2);;同时提前统一单位。现象:在混合外部直接使用混合内部定义的变量或嵌套混合,报错或结果不符合预期。
原因:混合存在作用域和调用上下文影响,不能按全局变量随意依赖。
修法:变量集中放到独立variables.less并由入口导入;混合内部变量只在调用上下文内使用,不依赖提升规则。现象:媒体查询嵌套后,
@media内部又重复写选择器,或误以为浏览器直接识别 Less 写法。
原因:媒体查询嵌套应围绕外层选择器组织,最终由 Less 编译成浏览器可识别的重复选择器结构。
修法:把@media嵌入目标选择器内部,内部直接写属性;检查编译产物是否符合预期。现象:把 Less 函数当混合用,期望函数生成一组样式;或用
%做取余。
原因:函数主要用于计算,不负责生成样式;%在 CSS 中有百分比语义,Less 不提供%取余运算。
修法:样式复用使用混合,计算使用函数;取余用mod(),百分比计算用percentage()。
练习
现有
variables.less定义品牌色,index.less作为入口文件。请写出合理的导入与编译组织方式,并说明哪些文件需要单独编译、哪些不需要。改写下面结构,使
hover只作用于li自身、> a只作用于直接子元素、& + &表示相邻同级项,并写出你认为会生成的关键选择器:less.nav { li { /* 在此补充 */ } }判断并修正下列写法中的运算问题,说明原因:
less.box { width: 100px / 2; height: (80% + 10em); margin: 100px % 6; }将下面传统媒体查询改写成 Less 嵌套写法,要求选择器不重复书写:
css.container { width: 100%; } @media (min-width: 768px) { .container { width: 750px; } } @media (min-width: 992px) { .container { width: 970px; } }场景题:
mixins.less中定义clearfix(),内部包含&::after。在.wrapper中调用该混合后,请说明生成的选择器结构;如果去掉&,结构会怎样变化?
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | Less导入 | 16:08 |
| 2 | Less嵌套 | 15:54 |
| 3 | 混合和嵌套的结合 | 10:14 |
| 4 | Less运算符 | 08:19 |
| 5 | Less函数 | 08:52 |
小结
- Less 导入的关键不是“能不能导入”,而是区分 Less 模块内联与 CSS 导入保留,入口文件负责统一编译。
- 嵌套用于表达结构,
&用于取消层级或拼接;二者混用时优先检查最终选择器是否符合预期。 - 媒体查询嵌套应减少选择器重复,但必须以编译产物可读、可维护为准。
- 混合负责样式复用,函数负责计算,不要把两者职责混在一起。
- 运算符的高频风险在单位与除法:单位提前统一,除法用括号明确表达。
- 变量、混合应集中管理并按模块拆分,不依赖作用域提升这类边缘行为。
- 函数按需掌握常用项即可,颜色函数和数学函数不必追求记全。
- 工程化视角下只编译入口文件,其他 Less 模块作为可组合、可维护的源码模块存在。