css预编译

前言

定义

我们使用css来编写样式,但是随着样式效果的多样化以及复杂化,css变量常量的缺失、语法的呆板等一成不变的写法就会十分臃肿难以维护。

所以基于css扩展了一套属于自己的语法,通过专门的编程语言,扩展css的编程能力,在编译成css。常见的库有less、scss/sass、stylus等。

特点

  • 完美兼容css代码,结构清晰便于扩展

  • 支持css定义变量常量、代码嵌套

  • 提供函数,支持循环语句

  • 支持模块化,通过混合(Mixins)实现复用

scss

安装

HTML使用

HTML不能使用scss文件,只能使用css文件,所以在使用scss时需要动态监听,然后引入编译之后的css静态文件。

// 全局安装
npm install sass -g

//局部安装
npm install sass

// 监听文件夹 
sass --watch scss:css

// 监听单个文件
sass --watch a.scss:a.css

按照上述操作之后,在书写样式表时使用scss进行开发,cmd会自动生成css文件

vue安装使用

vue使用scss可以通过两步安装,也可合二为一

// 分两步安装
// 安装sass-loader
npm install sass-loader --save-dev
// 安装dart-sass
npm install sass --save-dev

// 合二为一
npm i sass sass-loader -D

在.vue文件中使用

<style lang="scss" scoped>
……
</style>
react安装使用

安装sass-loader和node-sass依赖

npm install sass-loader node-sass --save-dev

打开react的webpack配置,找到module下的rules,oneof数组中,然后找到最后一个配置修改添加

{
  test:/\.scss$/,
  loaders: ['style-loader', 'css-loader', 'sass-loader']
}

import引入scss文件

import "./App.scss";

变量

有全局变量、局部变量和默认值。

sass的变量必须是 $ 开头,后面紧跟变量名,变量值和变量名之间需要使用冒号 : 分隔开,如果值后面加上 !default 则表示默认值。变量用在属性名中时,需要写在 #{ } 里面

<style lang="scss" scoped>
    $heightSize: 150px;                        // 全局变量
    $followUp: 'color';
    $themeColor: #55ff00 !default;            // 默认值,重新定义进行覆盖
    .div{
        $widthSize:300px;                    // 局部变量
        width:$widthSize;
        height: $heightSize;
        background-#{$followUp}: $themeColor;        // 在属性名中使用变量
    }
</style>

编译完成之后的css为

.div{
    width: 300px;
    height: 150px;
    background-color: #55ff00;
}

嵌套

代码嵌套进行后代选择,代码更直观,在选择嵌套中可是使用 & 表示父元素。并且除了选择器可以嵌套,属性和伪类伪元素也可以嵌套。属性嵌套指的是有些属性拥有同一个开始单词,如border-top,border-right都是以border开头

.div{
    width:300px;
    height: 300px;
    background-color: #55ff00;                
    .dot{
        width: 100px;
        height: 100px;
        background-color: pink;
        border: {
            top: 10px solid #000;
            right: 10px solid blue;
        };
        &::before{
            content: '我是before';
            font-size: 12px;
        }
        .text{
            font-size: 36px;
            color: red;
        }
    }
}

编译完成之后的css为

.div{
    width: 300px;
    height: 300px;
    background-color: #55ff00;
}
.div .dot {
    width: 100px;
    height: 100px;
    background-color: pink;
    border-top: 10px solid #000;
    border-right: 10px solid blue;
}
.div .dot::before {
    content: '我是before';
    font-size: 12px;
}
.div .dot .text{
    font-size: 36px;
    color: red;
}

混入(Mixins)

Mixins是css预处理语言最强大的特性,每一种完善的预处理都必不可少,可以将一部分公用样式抽出,作为独立定义的模块,然后再需要使用的地方直接调用。

声明的 @mixin 中还可以定义变量和接收参数,通过 @include 调用

无参数

scss文件编写

@mixin boxStyle {
    $bgc: pink;
    width: 300px;
    height: 300px;
    background-color: $bgc;
}
.box{
    @include boxStyle
}

编译完成之后的css为

.box{
    width: 300px;
    height: 300px;
    background-color: pink;
}
单一参数

scss文件编写

@mixin boxStyle($bgc: pink) {
    width: 300px;
    height: 300px;
    background-color: $bgc;
}
.box1{
    @include boxStyle        // 使用默认背景色 pink
}
.box2{
    @include boxStyle(blue)    // 背景色为 blue
}
.box3{
    @include boxStyle(yellow)    // 背景色为 yellow
}

编译完成之后的css为

.box1{
    width: 300px;
    height: 300px;
    background-color: pink;
}
.box2{
    width: 300px;
    height: 300px;
    background-color: blue;
}
.box3{
    width: 300px;
    height: 300px;
    background-color: yellow;
}
多个参数

scss文件编写

@mixin boxStyle($bgc: pink,$width:300px,$height:300px) {
    width: $width;
    height: $height;
    background-color: $bgc;
}
.box1{
    @include boxStyle(red)
}
.box2{
    @include boxStyle($width:100px)
}
.box3{
    @include boxStyle($height:150px,$bgc:#ccc)
}
.box4{
    @include boxStyle(#000, 200px, 50px)
}

编译完成之后的css为

.box1 {
    width: 300px;
    height: 300px;
    background-color: red;
}
.box2 {
    width: 100px;
    height: 300px;
    background-color: pink;
}
.box3 {
    width: 300px;
    height: 150px;
    background-color: #ccc;
}
.box4 {
    width: 200px;
    height: 50px;
    background-color: #000;
}

模块(Modules)

通过 @use 导入scss模块文件,自动生成一个命名空间,通过 . 语法访问模块里面的变量,只会引入和执行一次。而通过 @import 多次导入会进行多次编译

模块文件test.scss

$font-stack: Helvetica, sans-serif;
$text-color: #333;
$fontSize: 16px;

.span {
  font: 100% $font-stack;
  color: $text-color;
}

index文件导入使用

// 使用@use导入文件
@use 'test.scss' as test; // 生成了一个 test 命名空间

.box {
  background-color: test.$text-color;
  font-size: test.$fontSize
}

编译完成之后的css为

.span {
  font: 100% Helvetica, sans-serif;
  color: #333;
}

.box {
  background-color: #333;
  font-size: 16px;
}

继承(Extend)

继承可以让一个选择器继承另一个选择器的所有样式,在使用继承时使用 @extend 需要继承的选择器。

直接继承复用其他样式(在某些地方出错,不建议使用)

scss文件编写

.message-shared {
  border: 1px solid #ccc;
  padding: 10px;
  color: #333;
}
.message {
    width: 200px;
    height: 50px;
  @extend .message-shared;
}

编译完成之后的css为

.message {
    width: 200px;
    height: 50px;
    border: 1px solid #ccc;
    padding: 10px;
    color: #333;
}
使用占位符实现继承复用

scss文件编写

%message-shared {
    border: 1px solid #ccc;
    padding: 10px;
    color: #333;
}
.message {
    height: 50px;
    @extend %message-shared;
}
.success {
    @extend %message-shared;
    border-color: green;
}

编译完成之后的css为

.message {
    height: 50px;
    border: 1px solid #ccc;
    padding: 10px;
    color: #333;
}
.success {
    border: 1px solid green;
    padding: 10px;
    color: #333;
}

运算符(Operations)

可以对数值型的value进行加减乘除四则计算,以及使用+进行字符串拼接

scss文件编写

$containerSize:150px;        
$ballSize:10px;        
$dotn:36;        
.dot{
    font-size: $dotn * 0.5px;
    background-color: red;
    width: $containerSize + $ballSize;
    height: $containerSize - $ballSize;
    transform: rotate(360deg / $dotn) translateY(-$containerSize / 2 - $ballSize);
    &::before{
        content: '欢迎来到' + '复仇联盟';
    }
}

编译完成之后的css为

.dot {
    font-size: 18px;
    background-color: red;
    width: 160px;
    height: 140px;
    transform: rotate(10deg) translateY(-75px);
}
.dot::before {
    content: "欢迎来到复仇联盟";
}

控制指令——逻辑指令

通过 @if @else if @else 来实现条件判断

.h1{
    $type: monster;
    @if $type == ocean {
        color: blue;
    } @else if $type == matador {
        color: red;
    } @else if $type == monster {
        color: green;
    } @else {
        color: black;
    }
}
.h2{
    @if 1 + 1 == 2 { border: 1px solid; }
    @if 5 < 3 { border: 2px dotted; }
    @if null  { border: 3px double; }
}

编译完成之后的css为

.h1 {
    color: green;
}
.h2 {
    border: 1px solid;
}

控制指令——循环指令

支持for循环语句,通过 @for @each @while 实现循环,可以配合map和list使用

@for

包含两种格式:@for $var from <start> through <end>或者 @for $var from <start> to<end>,区别在于 through 与 to 的含义:当使用 through 时,条件范围包含 <start> 与 <end> 的值;而使用 to 时条件范围只包含 <start> 的值不包含 <end> 的值。$var 可以是任何变量,<start> 和 <end> 必须是整数值

@for $i from 1 through 3 {
  .item-#{$i} { width: 2em * $i; }
}
@for $i from 1 to 3 {
  .every-#{$i} { width: 10em * $i; }
}

编译完成之后的css为

.item-1 {
    width: 2em;
}
.item-2 {
    width: 4em;
}
.item-3 {
    width: 6em;
}
.every-1 {
    width: 10em;
}
.every-2 {
    width: 20em;
}
@each

@each 指令的格式是 $var in <list>, $var 可以是任何变量名<list> 是值列表。@each 将变量 $var 作用于值列表中的每一个项目,然后输出结果

@each $animal in puma, sea-slug, egret, salamander {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
  }
}

编译完成之后的css为

.puma-icon {
  background-image: url('/images/puma.png'); 
}
.sea-slug-icon {
  background-image: url('/images/sea-slug.png'); 
}
.egret-icon {
  background-image: url('/images/egret.png'); 
}
.salamander-icon {
  background-image: url('/images/salamander.png'); 
}

@each指令还可以使用多个变量,如@each $var1、$var2…… in<list>在里面如果是列表列表,则子列表的每个元素都被分配给相应的变量

@each $animal, $color, $cursor in (puma, black, default),(sea-slug, blue, pointer),(egret, white, move) {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
    border: 2px solid $color;
    cursor: $cursor;
  }
}

@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) {
  #{$header} {
    font-size: $size;
  }
}

编译完成之后的css为

.puma-icon {
  background-image: url('/images/puma.png');
  border: 2px solid black;
  cursor: default; 
}
.sea-slug-icon {
  background-image: url('/images/sea-slug.png');
  border: 2px solid blue;
  cursor: pointer; 
}
.egret-icon {
  background-image: url('/images/egret.png');
  border: 2px solid white;
  cursor: move; 
}

h1 {
  font-size: 2em; 
}
h2 {
  font-size: 1.5em; 
}
h3 {
  font-size: 1.2em; 
}
@while

@while 指令重复输出格式直到表达式返回结果为 false。这样可以实现比 @for 更复杂的循环,只是很少会用到。要注意避免陷入死循环

$i: 6;
@while $i > 0 {
  .item-#{$i} { width: 2em * $i; }
  $i: $i - 2;
}

编译完成之后的css为

.item-6 {
  width: 12em; 
}
.item-4 {
  width: 8em; 
}
.item-2 {
  width: 4em; 
}

扩展

颜色函数
lighten($color, 10%);           /* 返回的颜色在$color基础上变亮10% */
darken($color, 10%);            /* 返回的颜色在$color基础上变暗10% */
saturate($color, 10%);          /* 返回的颜色在$color基础上饱和度增加10% */
desaturate($color, 10%);        /* 返回的颜色在$color基础上饱和度减少10% */
grayscale($color);              /* 返回$color的灰度色*/
complement($color);             /* 返回$color的补色 */
invert($color);                 /* 返回$color的反相色 */
mix($color1, $color2, 50%);     /* $color1 和 $color2 的 50% 混合色*/
注释
/*
这是一个
多行注释
*/
// 这是一个单行注释
@import

Sass 拓展了 @import 的功能,允许其导入 SCSS 或 Sass 文件。被导入的文件将合并编译到同一个 CSS 文件中,另外,被导入的文件中所包含的变量或者混合指令 (mixin) 都可以在导入的文件中使用。

less

安装

HTML使用

less官网下载less.js文件,在.html文件中引入

<link rel="stylesheet/less" href='css/demo.less'>
<script type="text/javascript" src='./js/less.min.js'></script>
vue安装
// 分两步安装
// 安装less-loader
npm install less-loader --save-dev
// 安装dart-less
npm install less --save-dev

// 合二为一
npm i less less-loader -D
react安装

命令行操作安装

// 暴露webpack.config.js
npm run eject
// 安装
npm i less less-loader --save

配置webpack.config.js文件

// 在文件中按住Ctrl+F进行搜索,首先搜 style files regexes 找到位置后添加如下代码
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;

// 在文件中按住Ctrl+F进行搜索,搜 getStyleLoaders 找到位置后添加如下代码
{
  loader: require.resolve('less-loader'),
  options: lessOptions,
}

// 在文件中按住Ctrl+F进行搜索,搜 getCSSModuleLocalIdent 找到位置后添加如下代码
{
    test: lessRegex,
    exclude: lessModuleRegex,
    use: getStyleLoaders({
            importLoaders: 1,
            sourceMap: isEnvProduction && shouldUseSourceMap,
        },
        'less-loader'
    ),
    sideEffects: true,
},
{
    test: lessModuleRegex,
    use: getStyleLoaders({
            importLoaders: 1,
            sourceMap: isEnvProduction && shouldUseSourceMap,
            module: true,
            getLocalIdent: getCSSModuleLocalIdent
        },
        'less-loader'
    ),
},

变量

变量处理方式–懒加载,所有 Less 变量的计算,都是以这个变量最后一次被定义的值为准。Less的变量名使用 @ 符号开始。变量用在属性名中时,需要写在 @{ } 里面

<style lang="less" scoped>
    @width: 10px;
    @height: @width + 10px;
    @followUp: color;
    @themeColor: #55ff00;            
    #header {
            width: @width;
            height: @height;
            background-@{followUp}: @themeColor;        // 在属性名中使用变量
    }
</style>

编译完成之后的css为

#header {
    width: 10px;
    height: 20px;
    background-color: #55ff00;
}

嵌套

Less 提供了使用嵌套代替层叠或与层叠结合使用的能力,在选择嵌套中可是使用 & 表示父元素。

#header {
    color: black;
    .navigation {
        font-size: 12px;
    }
    .logo {
        width: 300px;
    }
    &::after {
        content: " ";
        font-size: 0;
        visibility: hidden;
    }
}

编译完成之后的css为

#header {
    color: black;
}
#header::after {
    content: " ";
    font-size: 0;
    visibility: hidden;
}
#header .navigation {
    font-size: 12px;
}
#header .logo {
    width: 300px;
}

混入(Mixins)

less的混合是一种将一组属性从一个规则集包含(或混入)到另一个规则集的方法,就像在当前的Class中增加一个属性一样。

在less可以将Mixins看成是一个类选择器,Mixins也可以设置参数,并给参数设置默认值。设置参数的变量名是使用 @ 开头,同样参数和默认参数值之间需要使用冒号 分隔开。

无参数
.bordered {
    border-top: dotted 1px black;
    border-bottom: solid 2px black;
    padding: 10px;
}
.item1{
    background-color: pink;
    .bordered()
}
.item2{
    background-color: red;
    .bordered
}

编译完成之后的css为

.item1 {
    background-color: pink;
    border-top: dotted 1px black;
    border-bottom: solid 2px black;
    padding: 10px;
}
.item2 {
    background-color: red;
    border-top: dotted 1px black;
    border-bottom: solid 2px black;
    padding: 10px;
}
有参数
.bordered(@width:2px,@pad:10px){
    border:@width solid red;
    padding: @pad;
}
.btn1 {
    .bordered(); 
}
.btn2 {
    .bordered(5px);
}    
.btn3{
    .bordered(@pad:5px)
}
.btn4{
    .bordered(3px, 20px)
}

编译完成之后的css为

.btn1 {
    border: 2px solid red;
    padding: 10px;
}
.btn2 {
    border: 5px solid red;
    padding: 10px;
}
.btn3 {
    border: 2px solid red;
    padding: 5px;
}
.btn4 {
    border: 3px solid red;
    padding: 20px;
}

运算符(Operations)

less一样可以进行四则运算

// 在加、减或比较之前会进行单位换算,最左侧操作数的单位类型为准
// 所有操作数被转换成相同的单位
@conversion-1: 5cm + 10mm; // 结果是 6cm
@conversion-2: 2 - 3cm - 5mm; // 结果是 -1.5cm
@incompatible-units: 2 + 5px - 3cm; // 结果是 4px

// 乘法和除法不作转换
@base: 2cm * 3mm; // 结果是 6cm

// 颜色计算
@color: (#224488 / 2); // 结果是 #112244
background-color: #112244 + #111; // 结果是 #223355

// calc() 并不对数学表达式进行计算,但是在嵌套函数中会计算变量和数学公式的值
@var: 50vh/2;
width: calc(50% + (@var - 20px));  // 结果是 calc(50% + (25vh - 20px))

控制指令——逻辑指令

LESS中通过guarded mixins代替if/else,利用关键词 when 来实现简单的条件判断

.bod (@num) when (@num > 3){
    border: 1px solid;
}
.bod (@num) when (@num < 3){
    border: 2px dotted;
}
.bod (@num) when (@num = 3){
    border: 3px double;
}
.btn1{.bod(5)}
.btn2{.bod(2)}
.btn3{.bod(3)}

编译完成之后的css为

.btn1 {
    border: 1px solid;
}
.btn2 {
    border: 2px dotted;
}
.btn3 {
    border: 3px double;
}

进行与或判断

/* 当下边 div 中 .size 传入的第一个参数是100px或者第二个参数是100px才会执行
(),()相当于JS中的|| 与判断*/
.size(@width,@height) when (@width = 100px),(@height = 100px){
  width: @width;
  height: @height;
}
div{
  .size(100px,100px);
  background: red;
}

/* 当下边 div 中 .size 传入的第一个参数是100px并且第二个参数是100px才会执行
()and()相当于JS中的&& 或判断*/
.size(@width,@height) when (@width = 100px) and (@height = 100px){
  width: @width;
  height: @height;
}
div{
  .size(100px,100px);
  background: red;
}

控制指令——循环指令

在 Less 中,混合可以调用它自身,当一个混合递归调用自身,再结合 guard 表达式和模式匹配这两个特性,就可以写出循环结构。

.xkd(@n, @i: 1) when (@i =< @n) {
  .grid@{i} {
    width: (@i * 100% / @n);
  }
  .xkd(@n, (@i + 1));
}
.xkd(5);

编译完成之后的css为

.grid1 {
  width: 20%;
}
.grid2 {
  width: 40%;
}
.grid3 {
  width: 60%;
}
.grid4 {
  width: 80%;
}
.grid5 {
  width: 100%;
}

扩展

颜色函数
lighten(@color, 10%);        // 返回的颜色在@color基础上变亮10%  
darken(@color, 10%);         // 返回的颜色在@color基础上变暗10%*/ 
saturate(@color, 10%);       // 返回的颜色在@color基础上饱和度增加10%
desaturate(@color, 10%);     // 返回的颜色在@color基础上饱和度降低10% 
spin(@color, 10);            // 返回的颜色在@color基础上色调增加10  
spin(@color, -10);           // 返回的颜色在@color基础上色调减少10 
mix(@color1, @color2);       // 返回的颜色是@color1和@color2两者的混合色 
注释
/*
这是一个
多行注释
*/
// 这是一个单行注释
@import

可以导入一个 .less 文件,此文件中的所有变量就可以全部使用了。如果导入的文件是 .less 扩展名,则可以将扩展名省略掉

stylus

安装

vue安装使用
npm install stylus

语法

//类似标准语法
p {
  color: #ffffff;
}
// omit brackets 省略花括号
p
  color: #ffffff;
// 省略花括号和分号
p
  color #ffffff

变量

Stylus对变量名没有任何限定,可以是$开始,也可以是任意字符,而且与变量值之间可以用冒号、空格隔开,并且不需要分配值给变量就可以定义引用属性

size = 10px
.top
  width: size

size = 20px
.btn
  width: size
 
.box
  width  w = 150px                 
  height  h = 80px                  
  margin-left  -(w / 2)            
  margin-top  -(h / 2)

编译完成之后的css为

.top {
      width: 10px;
}
.btn {
      width: 20px;
}
.box{
    width:150px;
    height:80px;
    margin-left:-75px;
    margin-top:-40px;
}

混合

可以不使用任何符号,就是直接声明Mixins名,然后在定义参数和默认值之间用等号(=)来连接。

bordered(myWidth=2px,pad=10px){
    border:myWidth solid red;
    padding:pad;
}
.btn1 {
    bordered(); 
}
.btn2 {
    bordered(5px);
}    
.btn3{
    bordered(pad=5px)
}
.btn4{
    bordered(3px, 20px)
}

编译完成之后的css为

.btn1 {
    border: 2px solid red;
    padding: 10px;
}
.btn2 {
    border: 5px solid red;
    padding: 10px;
}
.btn3 {
    border: 2px solid red;
    padding: 5px;
}
.btn4 {
    border: 3px solid red;
    padding: 20px;
}

逻辑指令和循环指令

Stylus中通过if、else if、else、unless(基本与if相反)实现条件判断来提供语言的流控制,通过for/in实现循环迭代。可以在样式中省略大括号({})。

// 逻辑
box(x, y, margin = false)
  padding y x
  if margin
    margin y x
  else
    padding y x    
body
  box(5px, 10px, true)

// 循环        
// for <val-name> [, <key-name>] in <expression> 
.box
  colors = red pink yellow blue
  for col, i in colors
    foo i col     

编译完成之后的css为

body{
    padding: 10px 5px;
    margin: 10px 5px;
}
.box {
    foo: 0 red;
    foo: 1 pink;
    foo: 2 yellow;
    foo: 3 blue;
} 

扩展

颜色函数
lighten(color, 10%); // 返回的颜色在'color'基础上变亮10%
darken(color, 10%);  // 返回的颜色在'color'基础上变暗10% 
saturate(color, 10%);  // 返回的颜色在'color'基础上饱和度增加10%
desaturate(color, 10%); // 返回的颜色在'color'基础上饱和度降低10% 
注释

注释与上相同

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值