Appearance
Less
简介
Less(Leaner Style Sheets)是一门CSS预处理语言,它扩展了CSS语言,增加了变量、混合(Mixins)、函数等特性,使CSS更易维护和扩展。Less可以运行在Node.js环境或浏览器环境中。
核心特性
变量
Less允许我们定义变量,使得样式值可以在多处重用:
less
// 定义变量
@primary-color: #3498db;
@secondary-color: #2ecc71;
@base-font-size: 16px;
@base-line-height: 1.5;
// 使用变量
.header {
background-color: @primary-color;
color: white;
font-size: @base-font-size;
line-height: @base-line-height;
}
.button {
background-color: @secondary-color;
border: 1px solid darken(@secondary-color, 10%);
font-size: @base-font-size;
}嵌套
Less允许CSS选择器以嵌套的方式编写,这样可以更好地反映HTML的结构:
less
.navigation {
background-color: #f8f8f8;
padding: 10px;
// 嵌套选择器
ul {
list-style: none;
margin: 0;
padding: 0;
li {
display: inline-block;
margin-right: 10px;
a {
color: @primary-color;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
}
// &符号引用父选择器
&.transparent {
background-color: transparent;
}
}混合(Mixins)
混合允许将一组属性从一个规则集包含(或混入)到另一个规则集中:
less
// 定义一个简单的混合
.bordered {
border: 1px solid #ddd;
border-radius: 4px;
}
// 带参数的混合
.border-radius(@radius) {
border-radius: @radius;
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
}
// 带默认参数的混合
.box-shadow(@x: 0, @y: 0, @blur: 1px, @color: #000) {
box-shadow: @arguments;
-webkit-box-shadow: @arguments;
-moz-box-shadow: @arguments;
}
// 使用混合
.box {
.bordered;
.border-radius(4px);
.box-shadow(2px, 2px, 5px, rgba(0, 0, 0, 0.3));
padding: 20px;
}
.button {
.border-radius(2px);
.box-shadow(0, 1px, 3px, rgba(0, 0, 0, 0.2));
background-color: @primary-color;
color: white;
}运算
Less支持算术运算,可以对数值和颜色进行加减乘除操作:
less
@base-margin: 10px;
@base-padding: 15px;
@base-font-size: 16px;
.container {
margin: @base-margin * 2;
padding: @base-padding + 5px;
}
.title {
font-size: @base-font-size * 1.5;
margin-bottom: @base-margin / 2;
}
// 颜色运算
@base-color: #111;
@light-color: #888 + #111; // 结果为 #999
@dark-color: #888 - #333; // 结果为 #555函数
Less内置了多种函数用于转换颜色、处理字符串和进行数学计算:
less
// 颜色函数
@base-color: #3498db;
@darker-color: darken(@base-color, 10%); // 使颜色变暗
@lighter-color: lighten(@base-color, 10%); // 使颜色变亮
@desaturated-color: desaturate(@base-color, 20%); // 降低饱和度
@alpha-color: fade(@base-color, 50%); // 设置透明度
.element {
color: @base-color;
background-color: @lighter-color;
border-color: @darker-color;
box-shadow: 0 0 5px @alpha-color;
}
// 数学函数
@value: 5.5;
.element {
width: round(@value) * 10px; // 四舍五入为6,然后乘以10px
height: ceil(@value) * 10px; // 向上取整为6,然后乘以10px
margin: floor(@value) * 10px; // 向下取整为5,然后乘以10px
}命名空间和访问符
可以将混合组织在命名空间中,然后使用>访问符引用它们:
less
#my-utility-library {
.button(@color) {
background-color: @color;
border: 1px solid darken(@color, 10%);
border-radius: 4px;
padding: 5px 15px;
&:hover {
background-color: lighten(@color, 10%);
}
}
.input(@border-color) {
border: 1px solid @border-color;
padding: 8px;
border-radius: 4px;
&:focus {
border-color: darken(@border-color, 20%);
outline: none;
}
}
}
// 使用命名空间中的混合
.primary-button {
#my-utility-library > .button(@primary-color);
}
.form-input {
#my-utility-library > .input(#ccc);
}导入
Less允许导入其他Less文件,这有助于模块化你的样式:
less
// 导入变量文件
@import "variables.less";
// 导入混合文件
@import "mixins/buttons.less";
@import "mixins/forms.less";
// 使用导入的变量和混合
.container {
max-width: @container-width;
margin: 0 auto;
.clearfix();
}条件语句与循环
条件混合(Guard表达式)
Less支持在混合中使用条件表达式:
less
// 根据参数值应用不同样式的混合
.text-style(@size) when (@size <= 14px) {
font-size: @size;
color: #333;
}
.text-style(@size) when (@size > 14px) and (@size <= 20px) {
font-size: @size;
color: #222;
font-weight: bold;
}
.text-style(@size) when (@size > 20px) {
font-size: @size;
color: #111;
font-weight: bold;
line-height: 1.2;
}
// 使用条件混合
.small-text {
.text-style(12px);
}
.medium-text {
.text-style(16px);
}
.large-text {
.text-style(24px);
}循环结构
Less没有显式的循环语句,但可以通过递归混合模拟循环:
less
// 创建网格系统的递归混合
.generate-columns(@n, @i: 1) when (@i =< @n) {
.col-@{i} {
width: (@i * 100% / @n);
}
.generate-columns(@n, (@i + 1));
}
// 生成12列网格系统
.generate-columns(12);
// 输出CSS将包含.col-1到.col-12的类,每个类有相应的宽度百分比工具与集成
命令行编译
使用Less命令行工具编译Less文件:
bash
# 安装Less全局命令行工具
npm install -g less
# 编译单个文件
lessc styles.less styles.css
# 压缩输出
lessc --compress styles.less styles.min.css
# 生成源映射
lessc --source-map styles.less styles.css与构建工具集成
Webpack
javascript
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}
]
}
};Gulp
javascript
// gulpfile.js
const gulp = require('gulp');
const less = require('gulp-less');
const autoprefixer = require('gulp-autoprefixer');
const cleanCSS = require('gulp-clean-css');
gulp.task('less', function() {
return gulp.src('./src/styles/**/*.less')
.pipe(less())
.pipe(autoprefixer())
.pipe(cleanCSS())
.pipe(gulp.dest('./dist/css'));
});最佳实践
文件组织
styles/
├── main.less # 主入口文件
├── variables.less # 变量定义
├── mixins/ # 混合目录
│ ├── buttons.less # 按钮相关混合
│ ├── forms.less # 表单相关混合
│ └── layout.less # 布局相关混合
├── components/ # 组件样式
│ ├── header.less # 头部组件
│ ├── footer.less # 底部组件
│ ├── navigation.less # 导航组件
│ └── forms.less # 表单组件
├── pages/ # 页面特定样式
│ ├── home.less # 首页样式
│ ├── about.less # 关于页样式
│ └── contact.less # 联系页样式
└── vendors/ # 第三方库样式覆盖
├── bootstrap.less # Bootstrap覆盖
└── jquery-ui.less # jQuery UI覆盖命名约定
- 使用连字符分隔的小写名称(kebab-case)命名类和ID
- 变量名应该描述其用途而不是值
- 使用有意义的前缀组织变量(如
@color-,@font-,@spacing-)
less
// 好的命名
@color-primary: #3498db;
@color-secondary: #2ecc71;
@font-size-base: 16px;
@spacing-unit: 8px;
// 避免这样命名
@blue: #3498db;
@green: #2ecc71;
@size: 16px;
@space: 8px;性能考虑
- 避免过度嵌套(不超过3-4层)
- 合理组织和复用混合
- 使用
&符号减少重复选择器
与Sass的对比
| 特性 | Less | Sass |
|---|---|---|
| 语法 | CSS扩展语法 | 有两种语法:SCSS(类CSS)和缩进语法 |
| 变量 | @变量名 | $变量名 |
| 作用域 | 有作用域,但有变量提升 | 严格的作用域规则 |
| 混合 | .mixin() | @mixin和@include |
| 嵌套规则 | 支持 | 支持 |
| 继承 | 通过混合实现 | 通过@extend实现 |
| 条件语句 | Guard表达式 | @if, @else |
| 循环 | 递归混合 | @for, @each, @while |
| 导入 | @import | @import, @use (Sass新版) |
| 函数 | 内置函数和自定义函数 | 内置函数和@function |
| 命名空间 | 支持 | 通过模块支持 |
| 运行环境 | 浏览器和Node.js | 只能预编译 |
常见问题与解决方案
变量作用域问题
less
// 问题:变量覆盖
@color: red;
.section {
@color: blue;
// 在这里,@color是blue
background: @color;
.subsection {
// 在这里,@color仍然是blue
color: @color;
}
}
// 解决方案:使用局部变量
.section {
@local-color: blue;
background: @local-color;
.subsection {
color: @local-color;
}
}混合与继承选择
less
// 使用混合(会复制所有属性)
.common-styles() {
border: 1px solid #ddd;
padding: 10px;
border-radius: 4px;
}
.box-1 {
.common-styles();
background: #f9f9f9;
}
.box-2 {
.common-styles();
background: #eaeaea;
}
// 更高效的方法:使用扩展
.common-styles {
border: 1px solid #ddd;
padding: 10px;
border-radius: 4px;
}
.box-1:extend(.common-styles) {
background: #f9f9f9;
}
.box-2:extend(.common-styles) {
background: #eaeaea;
}