主题
Less 的使用与Less 语法(Day19 2/3)
本页对应 Day19_PC项目&Less,共 5 段视频,约 1 小时 22 分。
学习目标
- 能使用 Less 定义普通变量及含特殊符号的变量值(如
~"..."),并在属性值中直接引用,编译结果正确。 - 能区分变量作为属性值、属性名和选择器三种使用场景,正确使用
@var或@{var},并通过编译结果验证。 - 能编写无参、有参、带默认值的 Less 混合,使用顺序传参和命名传参调用,并在调用处追加其他样式。
- 能使用
arguments获取混合实参列表,编写带浏览器私有前缀的box-shadow混合并验证生成的 CSS。 - 能利用同名混合与参数值匹配实现 Less 条件判断,按
up/down/left/right生成对应方向的纯 CSS 三角形。 - 能完成页面导航与路径导航的 HTML 结构和 Less 样式,使用 flex 布局、伪元素生成分隔符,并用
:not(:last-child)::after排除最后一项且通过页面效果验证。
知识点
一、Less 变量:把常用值先存起来
为什么需要:页面里颜色、长度会反复出现,散写难维护。转写稿先演示“左边 Less、右边 CSS”的对比,就是让变量集中管理常用值。
怎么想:变量用 @变量名: 值; 定义,使用时直接写 @变量名。
怎么做:
less
@len: 200px;
@master-red: #e60012;
@master-green: #080;
.box {
width: @len;
color: @master-red;
background: @master-red;
border-color: @master-green;
}易错点:变量名和值之间是冒号;变量名前必须有 @。转写稿说 Less 变量名没有 JS 那样的硬性命名规范,但仍建议取有意义的名字,如 @master-red、@len。
二、变量当属性名或选择器:要加大括号
为什么需要:不仅属性值想复用,属性名、选择器也可能想参数化。
怎么想:变量作为属性值可直接用;作为属性名或选择器,Less 编译时无法判断成分,需要 @{变量名}。
怎么做:
less
@prop: background-position;
@sel: .item;
@{sel} {
@{prop}: 10px 10px;
}易错点:转写稿调试时写 @prop: 10px 10px; 保存后 CSS 里根本没有 background-position,改成 @{prop} 才编译。选择器同理,直接 @sel { ... } 不生效,要写 @{sel}。
三、变量值含特殊符号:用 ~"..." 包起来
为什么需要:媒体查询条件里常有冒号、空格,如 (min-width: 768px);直接写会与“变量名:值”的冒号冲突。
怎么想:把整段值用波浪号加双引号包住,告诉 Less 里面是特殊字符串。
怎么做:
less
@min768: ~"(min-width: 768px)";
@media @min768 {
.box { width: 100%; }
}易错点:不包起来时,转写稿里出现“冒号分不清哪个是变量名”的编译冲突。空格、冒号这类特殊符号要按此处理。
四、混合:复用一组样式
为什么需要:类似 JS 自定义函数,把定位居中、阴影等一组样式复用。
怎么想:定义混合时在名字后加小括号,避免它本身被编译成类选择器;调用时也加括号。
怎么做:
less
.center-box(@w: 400px, @h: 300px) {
position: absolute;
width: @w;
height: @h;
left: 50%;
top: 50%;
margin-left: -(@w / 2);
margin-top: -(@h / 2);
}
.item {
.center-box(600px, 500px);
background: #ccc;
}易错点:转写稿中不加小括号时,混合会同时被当成类选择器输出;加了 () 后“不调用不编译”。带参混合少传、多传都会报错;除法要加括号,如 -(@w / 2)。默认参数在顺序传参时建议放后面;若放前面,只传一个会报错,按名字传参才更稳。调用也可按名字传参,如 .center-box(@h: 600px, @w: 800px);。
五、arguments 与条件判断
为什么需要:arguments 可取得实参列表,转写稿用它演示过 box-shadow 私有前缀兼容写法;条件判断则让 Less 根据参数值选择混合。
怎么做:
less
.box-shadow(@x, @y, @b, @o, @c) {
box-shadow: @arguments;
-webkit-box-shadow: @arguments;
-moz-box-shadow: @arguments;
}
.triangle(@w, @c, @dir) when (@dir = up) {
width: 0; height: 0;
border-width: @w;
border-style: solid;
border-color: transparent transparent @c transparent;
}
.triangle(@w, @c, @dir) when (@dir = down) {
width: 0; height: 0;
border-width: @w;
border-style: solid;
border-color: @c transparent transparent transparent;
}易错点:arguments 得到的是空格分隔的实参列表;转写稿强调它不像 JS 数组那样可随便遍历。条件判断本质是写多个同名混合,用 when 匹配第三个参数;传 down 不会调用 up 的混合,要再写 down 版本,类似 switch case。
六、在页面导航、路径导航中的调试
页面导航用 Less 配合伸缩盒:给容器定高后,子项在侧轴默认拉伸,能一起得到高度。路径导航里,转写稿用伪元素做斜杠,最后一个不能有斜杠,于是写成 .path span:not(:last-child)::after 排除最后一项;span 换行产生的空隙,则把父级设为 display:flex 消掉。调试时先看生成的选择器,再按“后代—伪类—伪元素”的顺序拆解,避免把组合选择器看混。
一、为什么需要 Less 变量
原生 CSS 里,一个主题色、一个版心宽度、一个常用长度,往往要在很多地方重复写。改一次就要全局搜索替换,容易漏改。Less 变量就是把这些“常用值”先存起来,用的时候再取。转写稿里反复强调:变量最常见的用途是存颜色、长度,使用时直接作为属性值。先想清楚“这个值会不会复用”,再决定是否定义变量;不要把只用一次、语义不清的值也塞成变量。
二、变量的定义与使用
定义变量用 @变量名: 值;,冒号左边是变量名,右边是值。普通值直接写;值里如果有冒号、空格等特殊符号,要用波浪号加双引号包起来,避免 Less 编译时把特殊符号误认为语法分隔符。
less
@len: 200px;
@master-red: #e60000;
@master-green: #008000;
.box {
width: @len;
color: @master-red;
background: @master-red;
}
@min768: ~"(min-width: 768px)";
@media @min768 {
.box { width: 100%; }
}怎么想:变量作为属性值时,直接 @变量名 使用;它既可以是单个属性值,也可以出现在复合属性中。易错点:值里有特殊符号却不用 ~"",编译会冲突;变量名虽然转写稿说“没有命名规范、随便叫”,但实际项目仍建议语义化,别用 a、b 这类名字。
三、变量作属性名和选择器
变量不仅能存属性值,还能存属性名、选择器。但这时不能直接写 @prop,要用 @{prop} 包起来。转写稿里演示:把 background-position 存进变量,直接写 @prop: ... 不会编译成属性名;写成 @{prop}: 10px 10px; 才生效。选择器同理。
less
@prop: background-position;
@sel02: ~".news .item";
.item {
@{prop}: 10px 10px;
}
@{sel02} {
color: @master-green;
}怎么想:Less 编译时需要判断 @ 后面是“取值”还是“拼名字”。作为属性值可直接取;作为属性名、选择器则要用 @{} 明确告诉编译器“这里要替换成名字”。易错点:选择器变量值里有空格时,也要用 ~"" 包起来,否则会引发语法错误。
四、混合:把重复样式封装起来
混合类似 JS 自定义函数:把一段样式封装起来,需要时调用。无参混合可以写成类选择器形式,但建议在名字后加小括号,避免它本身被编译成 CSS 类。
less
.center-box() {
position: absolute;
width: 400px;
height: 300px;
left: 50%;
top: 50%;
margin-left: -200px;
margin-top: -150px;
}
.item {
.center-box();
background: #fff;
}怎么想:先找重复样式,再抽成混合;调用后还可以继续追加当前元素自己的样式。易错点:不加小括号时,混合名本身也会作为类选择器输出到 CSS;不调用带参混合时,它不会编译,报错是正常的。
五、带参数、默认值与 @arguments
带参混合把变化的部分变成形参。调用时既可“按顺序传参”,也可“按名字传参”。有默认值的参数,按顺序传参时建议放后面;若放前面,按顺序传参容易错位,按名字传参则不受顺序限制。
less
.center-box02(@w, @h) {
width: @w;
height: @h;
left: 50%;
top: 50%;
margin-left: -(@w / 2);
margin-top: -(@h / 2);
}
.center-box03(@w: 1000px, @h: 400px) {
width: @w;
height: @h;
}
.a { .center-box02(600px, 500px); }
.b { .center-box02(@h: 600px, @w: 800px); }
.c { .center-box03(1200px); }@arguments 表示实参列表,转写稿用它演示过私有前缀兼容写法:把参数列表直接塞进 box-shadow 等属性中。易错点:参数个数不对、少传多传都会编译失败;除法要加小括号,如 -(@w / 2);@arguments 得到的是空格分隔的列表,不要想当然当成数组去遍历。
六、条件判断:用同名混合做分支
Less 没有 if/else,转写稿明确说它靠“混合 + when 条件”做判断。做法是写多个同名混合,用 when (@direction = up) 这类条件匹配不同实参。比如用纯 CSS 做三角形:宽高为 0,只留边框,把不需要的三个边框设为透明。
less
.triangle(@width, @color, @direction) when (@direction = up) {
width: 0; height: 0;
border-style: solid;
border-width: @width;
border-color: transparent transparent @color transparent;
}
.triangle(@width, @color, @direction) when (@direction = down) {
width: 0; height: 0;
border-style: solid;
border-width: @width;
border-color: @color transparent transparent transparent;
}
.arrow { .triangle(20px, #080, up); }怎么想:把“方向”作为分支条件,四个方向写四个同名混合。易错点:传入的方向没有对应 when 就不编译;条件里的变量名、等号、方向单词要写对;这种写法像 switch-case,但比 JS 啰嗦,适合少量分支。
七、案例:页面导航与路径导航
页面导航案例中,转写稿用 Flex 做布局:外层 .container 设 height: 50px; display: flex;,左侧分类设背景色、宽度、文字居中,右侧导航设 display: flex,链接设 margin: 0 22px; color: #333; font-size: 16px;。路径导航即“面包屑导航”,用伪元素生成斜杠,并排除最后一项:
less
.path span:not(:last-child)::after {
content: "/";
color: #ccc;
margin: 0 5px;
}
.path span { display: flex; }调试时注意:版心外层可加 min-width: 1200px,防止视口变窄后背景色断开;span 是行内元素,换行会产生空格,改成伸缩项目可消除多余间距。易错点:伪元素要加在 span 上而不是整个 .path 上;最后一个 span 要用 :not(:last-child) 排除,否则末尾多一个斜杠。
课堂画面





代码示例
示例 1:Less 变量(一般形式 / 特殊符号 / 作为属性名与选择器)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Less 变量</title>
<style type="text/less">
/* ① 一般形式:@变量名: 值; 冒号左边是名字,右边是值 */
@len: 100px;
@master-red: #e1251b;
@master-green: #080;
@border-width: 2px;
/* ② 值里带特殊符号(冒号、空格、括号)要用 ~"..." 包起来 */
@min768: ~"(min-width: 768px)";
@sel02: ~".item .title";
/* ③ 想把属性名、选择器存进变量 */
@prop: background-position;
@sel01: .item;
.box {
width: @len;
height: @len;
color: @master-red;
background-color: @master-green;
border: @border-width solid @master-red;
/* 变量作属性名:必须 @{变量名} */
@{prop}: 10px 10px;
/* 变量作选择器:同样必须 @{变量名} */
@{sel01} {
width: (@len / 2); /* 除法要自己加小括号 */
}
@{sel02} {
color: @master-red;
}
}
@media @min768 {
.box { width: 200px; }
}
</style>
<script src="https://cdn.jsdelivr.net/npm/less@4"></script>
</head>
<body>
<div class="box">
<div class="item"><div class="title">item / title</div></div>
</div>
</body>
</html>要点解释 / 易错点
- 定义变量固定格式:
@变量名: 值;,冒号是变量名和值的分界符;Less 变量名没有任何命名规范,@master-red、@a都能用。 - 变量作为属性值时直接
@len使用;作为属性名或选择器时必须写成@{prop}、@{sel01},不加大括号不会被编译出来(转写稿里@prop: 10px 10px;直接写就没有任何输出)。 - 值里出现特殊符号(冒号、空格等,例如媒体查询条件)要用
~"..."包起来,否则会和变量定义的分号/冒号冲突,编译报错。 - 除法
@len / 2必须用小括号包住,Less 新版本不会自动把/当除法算。
示例 2:Less 混合(无参 / 有参 / 默认值 / @arguments / 条件判断)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Less 混合与条件判断</title>
<style type="text/less">
/* ① 基本混合:名字后面加 (),不调用就不编译 */
.center-box01() {
position: absolute;
width: 400px;
height: 300px;
left: 50%;
top: 50%;
margin-left: -200px;
margin-top: -150px;
}
/* ② 带参数的混合 */
.center-box02(@width, @height) {
position: absolute;
width: @width;
height: @height;
left: 50%;
top: 50%;
margin-left: -(@width / 2);
margin-top: -(@height / 2);
}
/* ③ 带默认值的混合 */
.center-box03(@width: 100px, @height: 400px) {
position: absolute;
width: @width;
height: @height;
left: 50%;
top: 50%;
margin-left: -(@width / 2);
margin-top: -(@height / 2);
}
/* ④ @arguments:拿到全部实参组成的列表(空格分隔) */
.box-shadow(@x, @y, @b, @o, @color) {
box-shadow: @arguments;
-webkit-box-shadow: @arguments;
}
/* ⑤ 条件判断:同名混合 + when 守卫,相当于 switch-case */
.triangle(@w, @c, @direction) when (@direction = up) {
width: 0;
height: 0;
border-style: solid;
border-width: @w;
border-color: transparent transparent @c transparent; /* 下边框有色 → 箭头朝上 */
}
.triangle(@w, @c, @direction) when (@direction = down) {
width: 0;
height: 0;
border-style: solid;
border-width: @w;
border-color: @c transparent transparent transparent; /* 上边框有色 → 箭头朝下 */
}
.triangle(@w, @c, @direction) when (@direction = left) {
width: 0;
height: 0;
border-style: solid;
border-width: @w;
border-color: transparent @c transparent transparent; /* 右边框有色 → 箭头朝左 */
}
.triangle(@w, @c, @direction) when (@direction = right) {
width: 0;
height: 0;
border-style: solid;
border-width: @w;
border-color: transparent transparent transparent @c; /* 左边框有色 → 箭头朝右 */
}
/* 调用混合 */
.item01 { .center-box02(600px, 500px); background-color: pink; } /* 按顺序传参 */
.item02 { .center-box02(@height: 600px, @width: 800px); background-color: skyblue; } /* 按名字传参 */
.item03 { .center-box03(1000px); background-color: #ddd; } /* 只传一个,高度用默认值 */
.item04 { width: 200px; height: 100px; background: #fff; .box-shadow(3px, 10px, 15px, 0px, #ccc); }
.item05 { .triangle(20px, #080, up); }
.item06 { .triangle(20px, #080, down); }
.item07 { .triangle(20px, #080, left); }
.item08 { .triangle(20px, #080, right); }
</style>
<script src="https://cdn.jsdelivr.net/npm/less@4"></script>
</head>
<body>
<div class="item01">按顺序传参</div>
<div class="item02">按名字传参</div>
<div class="item03">默认值生效</div>
<div class="item04">@arguments</div>
<div class="item05"></div>
<div class="item06"></div>
<div class="item07"></div>
<div class="item08"></div>
</body>
</html>要点解释 / 易错点
- 混合名后一定要加
(),否则它会被当成类选择器编译进 CSS;加了()就“不调用不执行”,和 JS 函数一样。 - 有参混合传参有两种:按顺序(
600px, 500px)和按名字(@height: 600px, @width: 800px),按名字传参时顺序无所谓。 - 少传一个、多传一个参数都会报错(不编译),必须一一对应。
- 默认值用冒号不用等号:
@height: 400px。按顺序传参时,有默认值的参数必须写在后面;按名字传参时放前放后都可以。 @arguments就是全部实参组成的列表,空格分隔,适合一次性塞给box-shadow这类多值属性(老式加私有前缀的兼容写法)。- Less 没有 if 语法,条件判断靠同名混合 +
when守卫实现,传up/down/left/right匹配不同的混合,相当于switch-case;一个都匹配不上就什么都不输出。
示例 3:页面导航 + 路径导航(Less 嵌套 + Flex + 伪元素面包屑)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>页面导航 + 路径导航</title>
<style type="text/less">
@master-red: #e1251b;
@border-width: 2px;
* { margin: 0; padding: 0; }
a { text-decoration: none; color: #333; }
.container {
width: 1200px;
margin: 0 auto;
}
/* ---------- 页面导航 ---------- */
.nav-bar {
min-width: 1200px;
border-bottom: @border-width solid #ccc;
.container {
height: 50px;
line-height: 50px; /* 行高给容器,后代继承 */
display: flex;
}
.category {
width: 210px;
background-color: @master-red;
h2 {
text-align: center;
font-size: 14px;
color: #fff;
}
}
.nav {
display: flex;
a {
margin: 0 22px;
font-size: 16px;
color: #333;
}
}
}
/* ---------- 路径导航(面包屑) ---------- */
.product {
margin-top: 15px;
.pass-name {
display: flex; /* span 变伸缩项目,消除换行产生的空白 */
padding: 10px 0;
span {
&::after {
content: "/";
color: #ccc;
margin: 0 5px;
}
/* 最后一个 span 不生成斜杠 */
&:last-child::after {
content: "";
margin: 0;
}
}
}
}
</style>
<script src="https://cdn.jsdelivr.net/npm/less@4"></script>
</head>
<body>
<div class="nav-bar">
<div class="container">
<div class="category">
<h2>全部商品分类</h2>
</div>
<div class="nav">
<a href="#">手机数码</a>
<a href="#">电脑办公</a>
<a href="#">家用电器</a>
<a href="#">服装鞋包</a>
</div>
</div>
</div>
<div class="product">
<div class="container">
<div class="pass-name">
<span><a href="#">手机数码</a></span>
<span><a href="#">手机通讯</a></span>
<span><a href="#">Apple 苹果</a></span>
<span>iPhone 6S</span>
</div>
</div>
</div>
</body>
</html>要点解释 / 易错点
- 高度只给
.container写50px就够:它是伸缩容器,.category和.nav作为伸缩项目在侧轴(竖向)默认拉伸,高度自动跟容器一致。 - 行高写在
.container上会被后代继承,h2和a不用再单独写line-height。 - 面包屑的斜杠用
::after伪元素生成,&::after里的&表示“当前选择器”(即span),编译出来是.pass-name span::after;漏写&就变成后代选择器了。 - 最后一个
span要去掉斜杠,用&:last-child::after { content: ""; }覆盖掉content: "/",选择器一层层拆开读就不容易晕。 span是行内元素,HTML 换行会留下空格造成间距偏大,把.pass-name设为display: flex让span变伸缩项目,多余空白直接消失。- 页面主体给了
min-width: 1200px:窗口比版心窄时不会出现背景色断掉的情况(版心本身是固定 1200px)。
常见错误
- 现象:变量存属性名或选择器时,编译结果不生效或选择器错乱。原因:把变量当普通属性值直接使用。修法:属性名/选择器场景改为
@{变量名}。 - 现象:变量值含冒号、空格等符号时编译报错或解析错位。原因:特殊符号未转义包裹。修法:值写成
~"..."形式。 - 现象:定义混合后未调用,CSS 里却多出一个类选择器。原因:混合名后未加
()。修法:混合定义名后补(),只在调用时编译。 - 现象:调用带参混合时报错或不编译。原因:少传、多传,或按顺序传参时默认值参数放在前面。修法:参数个数对齐;默认值参数放后,或改用按名字传参。
- 现象:路径导航中最后一项仍出现斜杠,或空白区域也可点击。原因:伪元素加在
a上且未排除最后一项;可点击范围未收窄到文字。修法:伪元素加给内层span,用:not(:last-child)::after排除最后一项。 - 现象:窗口宽度小于版心时,外层背景色缺失或布局溢出。原因:外层容器未设最小宽度。修法:给相关外层容器设置
min-width为版心宽度。
练习
- 定义长度、主题色变量,并分别用于
width、color、background;再用变量存一个属性名和一个选择器,验证@{}写法。 - 定义两个变量:一个存媒体查询条件,一个存带空格的选择器;用
~"..."处理特殊符号并成功编译。 - 写一个无参混合实现元素水平垂直居中,再改写为带宽高参数的混合;分别用顺序传参和按名字传参调用。
- 写一个带默认值的混合,故意把默认值参数放前面,分别测试顺序传参和按名字传参的编译结果。
- 用同名混合实现三角形方向判断:传入
up/down/left/right时输出对应边框颜色与透明边框,并说明它对应哪种分支结构。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | Less变量 | 15:42 |
| 2 | 页面导航 | 07:17 |
| 3 | Less混合 | 26:00 |
| 4 | 路径导航 | 17:36 |
| 5 | Less条件判断 | 15:47 |
小结
- Less 变量既能存值,也能在特殊场景下参与属性名、选择器拼接,但写法不同。
- 变量值里的特殊符号必须显式处理,否则会干扰 Less 解析。
- 混合定义时加
()更符合“函数”语义,可避免无调用却被编译。 - 带参混合优先保证参数个数与传参方式匹配;默认值参数放后更稳妥。
arguments适合获取实参列表,但现代工程中不应再依赖它做兼容前缀库。- Less 的条件判断依赖同名混合匹配,本质更接近分支匹配而非真正
if。 - 页面导航、路径导航这类布局要同时关注结构层级、可点击区域、最后一项排除和最小宽度。
- 复杂选择器要按“后代/伪类/伪元素”逐段拆读,不能只凭整体感觉判断。