基础语法与核心特性
LESS基础语法与核心特性
快速入门
LESS简介
LESS(Leaner Style Sheets)是一种CSS预处理语言,它扩展了CSS,增加了变量、混合、函数等特性。LESS可以运行在客户端或服务器端。
LESS的主要优势:
- 提高代码复用性和可维护性
- 使CSS更加结构化和模块化
- 支持嵌套规则,减少重复选择器
- 提供计算功能,使样式更加灵活
- 兼容现有CSS语法,学习成本低
安装与环境配置
LESS可以通过npm安装:
npm install -g less
也可以在项目中本地安装:
npm install less --save-dev
在浏览器中使用LESS(不推荐用于生产环境):
<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="https://cdn.jsdelivr.net/npm/less@4.1.1"></script>
编译工具
LESS可以通过多种方式编译:
# 命令行编译
lessc styles.less styles.css
# 压缩输出
lessc styles.less styles.min.css --clean-css
# 生成Source Maps
lessc styles.less styles.css --source-map
常用的LESS编译工具:
命令行工具:less-watch-compiler
npm install -g less-watch-compiler less-watch-compiler src/less dist/css
构建工具集成:
- Webpack (less-loader)
- Gulp (gulp-less)
- Grunt (grunt-contrib-less)
编辑器插件:
- VS Code: Easy LESS
- Sublime Text: Less2Css
核心语法
变量系统
LESS使用@符号定义变量:
@primary-color: #007bff;
@font-size-base: 16px;
@line-height: 1.5;
.button {
background-color: @primary-color;
color: white;
font-size: @font-size-base;
line-height: @line-height;
}
变量插值(在选择器、属性名、URL和导入语句中使用变量):
@selector: banner;
@property: color;
@images: "../img";
@theme: "theme";
.@{selector} {
@{property}: #007bff;
background-image: url("@{images}/bg.png");
}
@import "@{theme}/dark.less";
变量作用域和懒加载:
@var: global;
.outer {
@var: outer;
.inner {
@var: inner;
value: @var; // 输出 inner
}
value: @var; // 输出 outer
}
value: @var; // 输出 global
嵌套规则
LESS允许CSS选择器嵌套,模拟HTML结构:
.header {
background-color: #f8f9fa;
.logo {
width: 100px;
height: 50px;
}
.navigation {
display: flex;
.nav-item {
margin: 0 10px;
a {
color: #333;
&:hover {
color: #007bff;
}
}
}
}
}
使用&
符号引用父选择器:
.button {
color: white;
background-color: #007bff;
&:hover {
background-color: #0069d9;
}
&-primary {
background-color: #007bff;
}
&-secondary {
background-color: #6c757d;
}
.disabled& {
opacity: 0.5;
pointer-events: none;
}
}
嵌套媒体查询:
.container {
width: 100%;
@media (min-width: 768px) {
width: 750px;
}
@media (min-width: 992px) {
width: 970px;
}
}
混合(Mixins)
混合允许将一组属性从一个规则集包含到另一个规则集:
// 定义混合
.bordered {
border: 1px solid #ddd;
border-radius: 4px;
}
// 使用混合
.box {
.bordered();
padding: 20px;
}
.card {
.bordered();
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
带参数的混合:
.border-radius(@radius) {
border-radius: @radius;
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
}
.button {
.border-radius(4px);
}
.avatar {
.border-radius(50%);
}
带默认参数的混合:
.box-shadow(@x: 0, @y: 2px, @blur: 4px, @color: rgba(0, 0, 0, 0.1)) {
box-shadow: @arguments;
-webkit-box-shadow: @arguments;
}
.card {
.box-shadow(); // 使用默认值
}
.modal {
.box-shadow(0, 5px, 15px, rgba(0, 0, 0, 0.3));
}
命名参数:
.gradient(@start-color, @end-color, @start-position: 0%, @end-position: 100%) {
background: linear-gradient(@start-position, @start-color, @end-position, @end-color);
}
.button {
.gradient(@end-color: #ff0000, @start-color: #ffff00);
}
运算
LESS支持数学运算:
@base-size: 16px;
@base-margin: 20px;
.container {
width: 100% - 20px;
margin: @base-margin / 2;
font-size: @base-size * 1.5;
line-height: (@base-size + 8px) / @base-size;
}
颜色运算:
@base-color: #007bff;
.button {
background-color: @base-color;
border-color: darken(@base-color, 10%);
&:hover {
background-color: lighten(@base-color, 10%);
}
}
.alert {
background-color: fade(@base-color, 20%);
border-color: @base-color;
}
函数
LESS提供了多种内置函数:
// 颜色函数
@base-color: #007bff;
.element {
color: darken(@base-color, 10%);
background-color: lighten(@base-color, 40%);
border-color: saturate(@base-color, 20%);
box-shadow: 0 0 5px fade(@base-color, 50%);
}
// 数学函数
@value: 3.5;
.element {
width: round(@value) + px;
height: ceil(@value) + px;
margin: floor(@value) + px;
padding: percentage(0.5); // 输出 50%
}
// 字符串函数
@path: "assets/images";
@file: "logo.png";
.logo {
background-image: url("@{path}/@{file}");
content: ~"data-image='@{file}'";
}
自定义函数(通过混合模拟):
.calculate-width(@columns, @total: 12) {
@result: percentage(@columns / @total);
width: @result;
}
.col-6 {
.calculate-width(6);
}
.col-4 {
.calculate-width(4);
}
导入
LESS扩展了CSS的@import
规则:
// 导入其他LESS文件
@import "variables.less";
@import "mixins.less";
// 省略扩展名
@import "variables";
@import "mixins";
// 导入CSS文件(不会被处理)
@import (css) "reset.css";
// 只导入一次
@import (once) "common";
// 多次导入
@import (multiple) "common";
// 导入但不编译
@import (reference) "mixins";
条件语句
LESS中的条件语句通过guard混合实现:
.mixin(@value) when (@value > 10) {
font-size: @value * 1px;
}
.mixin(@value) when (@value <= 10) {
font-size: @value * 0.5px;
}
.element-1 {
.mixin(12); // 应用第一个混合
}
.element-2 {
.mixin(8); // 应用第二个混合
}
逻辑运算符:
.mixin(@value) when (@value > 10) and (@value < 20) {
// 当value大于10且小于20时应用
font-size: @value * 1px;
}
.mixin(@value) when (@value <= 10), (@value >= 20) {
// 当value小于等于10或大于等于20时应用
font-size: @value * 0.5px;
}
.mixin(@value) when not (@value = 15) {
// 当value不等于15时应用
color: blue;
}
类型检查:
.mixin(@value) when (isnumber(@value)) {
// 当value是数字时应用
width: @value * 1px;
}
.mixin(@value) when (iscolor(@value)) {
// 当value是颜色时应用
background-color: @value;
}
.element-1 {
.mixin(20);
}
.element-2 {
.mixin(#007bff);
}
循环
LESS没有内置循环结构,但可以通过递归混合模拟:
.generate-columns(@n, @i: 1) when (@i =< @n) {
.col-@{i} {
width: percentage(@i / @n);
}
.generate-columns(@n, (@i + 1));
}
// 生成12列网格系统
.generate-columns(12);
命名空间
使用命名空间组织混合:
#utilities {
.center() {
display: flex;
justify-content: center;
align-items: center;
}
.clearfix() {
&::after {
content: "";
display: table;
clear: both;
}
}
}
.container {
#utilities.center();
}
.row {
#utilities.clearfix();
}
映射
LESS 3.5+支持映射:
@breakpoints: {
xs: 576px;
sm: 768px;
md: 992px;
lg: 1200px;
};
.element {
@media (min-width: @breakpoints[xs]) {
width: 540px;
}
@media (min-width: @breakpoints[md]) {
width: 960px;
}
}
转义
使用~
符号进行转义,允许使用任意字符串作为属性值:
.element {
filter: ~"progid:DXImageTransform.Microsoft.gradient(startColorstr=#55000000, endColorstr=#55ffffff)";
-ms-filter: ~"progid:DXImageTransform.Microsoft.gradient(startColorstr=#55000000, endColorstr=#55ffffff)";
}
注释
LESS支持CSS的标准注释和单行注释:
/* 这是一个多行注释,会保留在编译后的CSS中 */
// 这是一个单行注释,不会出现在编译后的CSS中
高级特性
父选择器引用
&
符号的高级用法:
.header {
&-logo {
// 编译为 .header-logo
width: 100px;
}
&__navigation {
// 编译为 .header__navigation (BEM风格)
display: flex;
}
.theme-dark & {
// 编译为 .theme-dark .header
background-color: #333;
}
body.fixed-nav & {
// 编译为 body.fixed-nav .header
position: fixed;
}
}
继承
使用:extend
伪类实现继承:
.button {
display: inline-block;
padding: 6px 12px;
border: 1px solid transparent;
border-radius: 4px;
}
.btn-primary {
&:extend(.button);
background-color: #007bff;
color: white;
}
.btn-secondary {
&:extend(.button);
background-color: #6c757d;
color: white;
}
多重继承:
.clickable {
cursor: pointer;
}
.btn-primary {
&:extend(.button, .clickable);
background-color: #007bff;
}
合并
属性合并允许将多个值组合到单个属性中:
// 使用逗号合并
.mixin() {
box-shadow+: 0 1px 3px rgba(0, 0, 0, 0.12);
}
.box {
.mixin();
box-shadow+: 0 1px 2px rgba(0, 0, 0, 0.24);
// 编译为: box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
// 使用空格合并
.mixin() {
transform+_: scale(1.2);
}
.element {
.mixin();
transform+_: rotate(30deg);
// 编译为: transform: scale(1.2) rotate(30deg);
}
实用技巧
避免编译
有时需要输出不符合LESS语法但有效的CSS语法,可以使用~
转义:
.element {
width: ~"calc(100% - 20px)";
// 编译为: width: calc(100% - 20px);
}
检测浏览器
使用条件混合检测IE浏览器:
.mixin() when (@is-ie) {
.element {
background-color: red;
}
}
// 在使用前设置变量
@is-ie: true;
.mixin();
创建主题
使用变量和混合创建可切换的主题:
// 定义主题变量
@theme: "light"; // 或 "dark"
// 主题颜色映射
@themes: {
light: {
bg-color: #ffffff;
text-color: #333333;
border-color: #dddddd;
};
dark: {
bg-color: #222222;
text-color: #f5f5f5;
border-color: #444444;
};
};
// 获取当前主题的颜色
.themed() {
background-color: @themes[@theme][bg-color];
color: @themes[@theme][text-color];
border-color: @themes[@theme][border-color];
}
// 应用主题
.card {
.themed();
padding: 20px;
}
创建网格系统
使用LESS创建响应式网格系统:
// 定义网格变量
@columns: 12;
@gutter-width: 30px;
@container-width: 1200px;
// 创建行
.row {
display: flex;
flex-wrap: wrap;
margin-left: -(@gutter-width / 2);
margin-right: -(@gutter-width / 2);
}
// 创建列混合
.make-col(@size) {
flex: 0 0 percentage(@size / @columns);
max-width: percentage(@size / @columns);
padding-left: (@gutter-width / 2);
padding-right: (@gutter-width / 2);
}
// 生成列类
.generate-columns(@n, @i: 1) when (@i =< @n) {
.col-@{i} {
.make-col(@i);
}
.generate-columns(@n, (@i + 1));
}
// 生成所有列
.generate-columns(@columns);
// 容器
.container {
max-width: @container-width;
margin-left: auto;
margin-right: auto;
padding-left: 15px;
padding-right: 15px;
}
创建响应式工具
使用LESS创建响应式工具:
// 定义断点
@breakpoints: {
xs: 0;
sm: 576px;
md: 768px;
lg: 992px;
xl: 1200px;
};
// 媒体查询混合
.media-up(@breakpoint) {
@min-width: @breakpoints[@breakpoint];
@media (min-width: @min-width) {
@content();
}
}
.media-down(@breakpoint) {
@max-width: @breakpoints[@breakpoint];
@media (max-width: @max-width - 1) {
@content();
}
}
// 使用示例
.element {
font-size: 14px;
.media-up(md, {
font-size: 16px;
});
.media-up(lg, {
font-size: 18px;
});
}
与CSS模块化方案比较
LESS vs SASS/SCSS
LESS和SASS/SCSS的主要区别:
语法:
- LESS使用CSS风格的语法,使用
@
作为变量前缀 - SASS/SCSS使用
$
作为变量前缀,SCSS更接近CSS语法
- LESS使用CSS风格的语法,使用
编译环境:
- LESS可以在浏览器端编译(虽然不推荐)
- SASS/SCSS需要在服务器端或构建过程中编译
功能:
- SASS/SCSS提供更多高级功能,如控制指令(@if, @for, @each)
- LESS通过混合和guard实现类似功能,但语法不同
变量作用域:
- LESS变量支持懒加载和作用域提升
- SASS/SCSS变量遵循更严格的作用域规则
LESS vs PostCSS
LESS和PostCSS的比较:
定位:
- LESS是一种预处理器,扩展CSS语法
- PostCSS是一个工具平台,通过插件转换CSS
灵活性:
- LESS提供固定的语法和功能集
- PostCSS通过插件系统提供高度可定制的功能
性能:
- PostCSS通常比LESS更快,因为它可以只应用需要的转换
- LESS需要处理整个语法树
用途:
- LESS适合需要变量、嵌套和混合的项目
- PostCSS适合需要特定CSS转换的项目(如Autoprefixer)
LESS vs CSS-in-JS
LESS和CSS-in-JS的比较:
分离程度:
- LESS保持样式和JavaScript分离
- CSS-in-JS将样式直接嵌入JavaScript代码
动态性:
- CSS-in-JS可以基于组件状态动态生成样式
- LESS在编译时生成静态CSS
作用域:
- CSS-in-JS通常提供自动的样式作用域
- LESS需要手动管理选择器命名以避免冲突
构建过程:
- LESS需要编译步骤
- CSS-in-JS可以在运行时处理样式
最佳实践
文件组织
推荐的LESS文件组织结构:
styles/
├── base/
│ ├── _reset.less
│ ├── _typography.less
│ └── _variables.less
├── components/
│ ├── _buttons.less
│ ├── _forms.less
│ └── _navigation.less
├── layouts/
│ ├── _footer.less
│ ├── _grid.less
│ └── _header.less
├── mixins/
│ ├── _breakpoints.less
│ └── _utilities.less
├── pages/
│ ├── _home.less
│ └── _about.less
└── main.less
主文件示例:
// main.less
// 导入基础样式
@import "base/_variables";
@import "base/_reset";
@import "base/_typography";
// 导入混合
@import "mixins/_breakpoints";
@import "mixins/_utilities";
// 导入布局
@import "layouts/_grid";
@import "layouts/_header";
@import "layouts/_footer";
// 导入组件
@import "components/_buttons";
@import "components/_forms";
@import "components/_navigation";
// 导入页面特定样式
@import "pages/_home";
@import "pages/_about";
命名约定
推荐的命名约定:
变量命名:
@primary-color: #007bff; @font-size-base: 16px; @spacing-unit: 8px;
BEM命名法:
.block { &__element { // 元素样式 &--modifier { // 修饰符样式 } } }
混合命名:
.make-button(@color, @padding: 10px) { // 混合内容 }
性能优化
LESS性能优化技巧:
减少嵌套深度:
// 不推荐 .header { .navigation { ul { li { a { // 样式 } } } } } // 推荐 .header-navigation-link { // 样式 }
避免过度使用混合:
// 不推荐 - 每次使用都会复制所有CSS .box-shadow() { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12); } // 推荐 - 使用继承 .box-shadow { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12); } .card { &:extend(.box-shadow); }
优化选择器:
// 不推荐 div.container .row > div.col .card { // 样式 } // 推荐 .card { // 样式 }
调试技巧
LESS调试技巧:
使用Source Maps:
lessc styles.less styles.css --source-map
使用注释:
// 这是一个调试注释,不会出现在编译后的CSS中 /* 这是一个会保留在编译后CSS中的注释 */
检查编译输出:
lessc styles.less | less
总结
LESS是一个强大的CSS预处理器,它通过变量、嵌套、混合、函数等特性扩展了CSS的功能。本文详细介绍了LESS的基础语法和核心特性,包括:
- 变量系统和作用域
- 嵌套规则和父选择器引用
- 混合和参数化混合
- 运算和函数
- 导入和模块化
- 条件语句和循环
- 命名空间和映射
- 继承和属性合并
- 实用技巧和最佳实践
通过掌握这些特性,开发者可以编写更加模块化、可维护和可扩展的CSS代码,提高前端开发效率。