【查缺补漏】css、Less、Sass定义变量,混合,嵌套,运算等(内含10道面试题)

一. 定义变量

1.CSS 的变量声明和使用

定义 3 个变量,:root 使得所有人可访问

:root{
  --base: yellow;
  --spacing: 10px;
  --blur: 10px;
}


使用上面定义的变量作为属性值:

img{
  filter: blur(var(--blur));
  padding: var(--spacing);
  background: var(--base);
}

 

还可以通过js改变变量的值,从而改变属性

 document.documentElement.style.setProperty(`--${this.name}`,this.value + suffix)
 // ${this.name}是解析变量的写法

2.Less 的变量声明和使用

@charset "utf-8";
//定义变量
 @test-width:200px;
 @test-height:300px;
 //定义样式
 .testDiv{
    width:@test-width;
    height:@test-height;
    background-color: aquamarine;
}

3.Sass 的变量声明和使用

Sass 的变量必须是$开头,后面紧跟变量名,而变量值和变量名之间就需要使用冒号(:)分隔开(就像CSS属性设置一样),如果值后面加上!default则表示默认值。 这里写图片描述

(1) 普通变量:定义之后可以在全局范围内使用。

Sass语法:

$fontSize: 12px;
body{
  font-size:$fontSize;
}

css输出:

body{
    font-size:12px;
}

(2) 默认变量:Sass 的默认变量仅需要在值后面加上!default 即可。

Sass语法

$baseLineHeight: 2;
$baseLineHeight: 1.5 !default;
body{
 line-height: $baseLineHeight;
}

 

css输出:

body{
 line-height:2;
}

可以看出现在编译后的 line-height 为 2,而不是我们默认的 1.5。默认变量的价值在进行组件化开发的时候会非常有用。

(3) 特殊变量:一般我们定义的变量都为属性值,可直接使用,但是如果变量作为属性或在某些特殊情况下等则必须要以#{$variables}形式使用

Sass语法

$borderDirection: top !default;
$baseFontSize: 12px !default;
$baseLineHeight: 1.5 !default;

// 应用于class和属性
.border-#{$borderDirection}{
  border-#{$borderDirection}:1px solid #ccc;
}
// 应用于复杂的属性值
body{
    font:#{$baseFontSize}/#{$baseLineHeight};
}

 

CSS输出:

.border-top{
  border-top:1px solid #ccc;
}
body {
  font: 12px/1.5;
}

(4)多值变量:多值变量分为 list 类型和 map 类型,简单来说 list 类型有点像 js 中的数组,而 map 类型有点像 js 中的对象。

list

  • list 数据可通过空格,逗号或小括号分隔多个值,可用 nth(var,var,index)取值。

  • list 数据操作还有很多其他函数如:length($list), join(list1,list1,list2,[$separator]), append(list,list,value,[$separator]), 更多请参考Sass Functions

Sass语法

$linkColor:#08c #333 !default;//第一个值为默认值,第二个鼠标滑过值
a{
  color:nth($linkColor,1);
  &:hover{
    color:nth($linkColor,2);
  }
}

css输出

a {
  color: #08c;
}
a:hover {
  color: #333;
}

 

map

  • map 数据以 key 和 value 成对出现,其中 value 又可以是 list

  • 格式为:$map: (key1: value1, key2: value2, key3: value3)

  • 通过map-get(map,map,map)

  • 更多请参考Sass Functions

定义:

$heading: (h1: 2em, h2: 1.5em, h3: 1.2em);

Sass编译

$key-green: green;
$val-green: #fff;
$key-red: red;
$val-red: #ff0000;
$key-info: info;
$val-info: #ff00ff;
$key-success: success;
$val-success: #f66;

//$text: (green: #fff, red: #ff0, info: #f0f);
$text: (
    $key-green: $val-green,
    $key-red: $val-red,
    $key-info: $val-info,
    $key-success:$val-success
);

@each $i, $size in $text {
    .text-#{$i} {
        color: $size;
    }
}

css输出

.text-green {
  color: #fff;
}

.text-red {
  color: #ff0000;
}

.text-info {
  color: #ff00ff;
}

.text-success {
  color: #f66;
}

(5) 全局变量:在变量值后面加上!global即为全局变量。

Sass编译

$fontSize: 12px;
$color: #333 !global;
body{
    $fontSize: 14px;
    font-size: $fontSize;
}
p{
    font-size: $fontSize;
    color: $color;
}

 

css输出

body {
  font-size: 14px;
}
p {
  font-size: 12px;
  color: #333;
}

这里设置了两个变量,然后在body里面重新设置了下,有点不同的是对于 $color变量,我们设置了!global。通过编译后的css可以看到font-size取值不同,而color取值相同。与上面的机制对比就会发现默认在选择器里面的变量为局部变量,而只有设置了!global之后才会成为全局变量。

二. Less 和 Sass 的共性

1.混合(Mixins):class 中的 class

混合(Mixins)就是将一组属性的规则集混入到另一组规则集中, 用于定义可重复使用的样式,例如 flex 布局,日常开发也是高频使用。

Less 中的混合使用

.flex() {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
}
.cell-line {
   .flex();
   font-size: 16px;
}

Sass 中的混合使用

// 定义混合指令, 语法: @mixin后面添加名称及样式
@mixin flex() {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
}
// 引用混合指令, 语法: @include后面添加名称及参数(可选)
.cell-line {
   @include flex;
   font-size: 16px;
}

2.参数混合(Parametric):可以像函数一样传递参数的 class

Parametric: 带参数混入,就是可以像函数一样将参数传递给要混入的 class 中, 另外定义时可设置默认值,不传时则使用默认值。

Less 中的参数混合使用

.flex(@direction: row, @items: initial, @content: initial) {
    display: flex;
    flex-direction: @direction;
    align-items: @items;
    justify-content: @content;
}
.cell-line {
  .flex(row, center);
  font-size: 16px;
}

Sass 中的参数混合使用

@mixin flex($direction: row, $items: initial, $content: initial) {
    display: flex;
    flex-direction: $direction;
    align-items: $items;
    justify-content: $content;
}
.cell-line {
  @include flex(row, center);
  font-size: 16px;
}

3.嵌套规则(Nested Rules):class 中嵌套 class,从而减少重复的代码

Nested 就是在一个选择器中再嵌套其子级选择器, 使其结构清晰,增加代码可读性。

Less 的嵌套规则

.list {
  background: #fff;
  .item {
     color: #de432a
  }
}

(1)在嵌套中,&表示父级选择器 , 而不是子级选择器, 在 Sass 中也是一样的。

Less 语法

a {
  color: blue;
  &:hover {
    color: green;
  }
}


css编译

a {
  color: blue;
}
a:hover {
  color: green;
}

(2) @ 规则(例如 @media 或 @supports)可以与选择器以相同的方式进行嵌套。@ 规则会被放在前面,同一规则集中的其它元素的相对顺序保持不变。即冒泡(bubbling)。

Less 语法

.component {
  width: 300px;
  @media (min-width: 768px) {
    width: 600px;
    @media  (min-resolution: 192dpi) {
      background-image: url(/img/retina2x.png);
    }
  }
  @media (min-width: 1280px) {
    width: 800px;
  }
}


css编译

.component {
  width: 300px;
}
@media (min-width: 768px) {
  .component {
    width: 600px;
  }
}
@media (min-width: 768px) and (min-resolution: 192dpi) {
  .component {
    background-image: url(/img/retina2x.png);
  }
}
@media (min-width: 1280px) {
  .component {
    width: 800px;
  }
}

注:该示例引入自官网,嵌套规则

Sass 的属性嵌套

像 font-size, font-family, font-weight 等都是以 font 为属性命名空间, 在 Sass 中允许将属性嵌套在命名空间中。

Sass 语法

.list {
  font {
    size: 12px;
    weight: bold;
    family: Arial, Tahoma, 'Microsoft Yahei', '\5b8b\4f53', sans-serif;
  }
}

css 编译

.list {
  font-size: 12px;
  font-weight: bold;
  font-family: Arial, Tahoma, 'Microsoft Yahei', '\5b8b\4f53', sans-serif;
}

4.运算(Operations):css 中的数学计算

算术运算符 +、-、*、/ 可以对任何数字、颜色或变量进行运算。在+,-运算中,单位不同时,会进行单位换算, 以左侧操作数单位类型为准。

Less 运算使用

  @bgColor: #112233 + #134; //结果为 #225577

calc 特例

为了与 CSS 保持兼容,在 Less 中 calc() 并不对数学表达式进行计算,但是在嵌套函数中会计算变量和数学公式的值

@topHeight: 46px;
.list {
  height: calc(100vh - @topHeight);
}

Sass 运算使用

p {
  color: #010203 * 2; //结果为 color: #020406;
}
//注: 运算时,必须为相同alpha值, 即同为rgba或者hsla.

从 CSS 优化角度思考, 应避免使用 CSS 表达式(Expression)。一个 CSS 表达式会反复执行,因为需要不停的去计算 CSS 的属性值,甚至可能会执行成千上百次,所以应当减少使用。

5.颜色功能(Color function):可以编辑你的颜色

颜色的函数运算,颜色会先被转化成 HSL 色彩空间,然后在通道级别操作。

Less

p {
  color: hsl(90, 100%, 50%)
}
//更多请查阅Less的 [色彩函数](https://Less.bootcss.com/functions/#color-definition-functions)

Sass

p {
  color: hsl(0, 100%, 50%);
}
// css编译为:
p {
  color: #ff0000;
}

6.命名空间(Namespaces):样式分组,从而方便被调用

将一些变量或者混合模块打包封装,这样就可以更好的组织 CSS 和属性集的重复使用。

@colorBg: #f51861;
#bundle {
  .button{
    color: #fff;
    background: @colorBg;
    &:hover {
      background: green;
    }
  }
  .tab {...}
  .cell-line{...}
}
//使用
p {
  padding: 10px;
  #bundle .button();
}
//注: Sass也是一样的道理,语法略有不同。

7.作用域(Scope):局部修改样式

Less 的作用域与 css 类似, 首先在本地查找变量和属性, 没找到, 则从父级作用域继承。

@color:#333;
.list {
  @color: #f51861;
  .item {
    color:@color; // #f51861
  }
}

 

Sass 支持两种类型变量:局部变量和全局变量,一般情况下选择器外的为全局变量,选择器内的为局部变量。

@mixin button-style {
  $btn-bg-color: lightblue;
  color: $btn-bg-color;
}
.button {
  @include button-style
}
//css编译
.button {
  color: lightblue;
}

如果是在某个选择器中使用这个变量, 会怎么样呢?

.btn {
  background:  $btn-bg-color; //报错 Undefined variable ‘$btn-bg-color’,因为全局并没有该变量存在。
}

8.JavaScript 表达式(Javascript evaluation):在 CSS 样式中使用 Javascript 表达式赋值

Less

@some: foo;
div {
  margin: if((2 > 1), 0, 3px);
  color:  if((iscolor(@some)), @some, black);
}
//css编译
div {
  margin: 0;
  color:  black;
}

Sass

p {
  @if 1 + 1 == 2 { border: 1px solid; }
  @if 5 < 3 { border: 2px dotted; }
  @if null  { border: 3px double; }
}
//css编译
p {
  border: 1px solid;
}

三.相关面试题

1.什么是 CSS 预处理器?

CSS 预处理器用一种专门的编程语言,进行 Web 页面样式设计,然后再编译成正常的 CSS 文件,以供项目使用。CSS 预处理器为 CSS 增加一些编程的特性,无需考虑浏览器的兼容性问题.
目前主流的 CSS 预处理器语言有 Sass、Less、stylus 等。

实现原理:

  • 取到 DSL 源代码 的 分析树

  • 将含有动态生成相关节点的分析树 转换为 静态分析树

  • 将 静态分析树 转换为 CSS 的 静态分析树

  • 将 CSS 的 静态分析树 转换为 CSS 代码

2.什么是 CSS 后处理器?

对 CSS 进行处理,并最终生成 CSS 的 预处理器,它属于广义上的 CSS 预处理器, 可以对 css 自动处理兼容性问题。
以 Autoprefixer 为例:

.container {
  display: flex;
}
.item {
  flex: 1;
}

将以上标准 CSS,编译为处理了兼容性的 生产环境 CSS:

.container {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
}
.item {
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -ms-flex: 1;
  flex: 1;
}

可以看到,编译前 与 编译后 的代码都是 CSS

实现原理

  • 将源代码做为 CSS 解析,获得分析树

  • 对 CSS 的分析树进行后处理

  • 将 CSS 的分析树 转换为 CSS 代码

3.Less 和 Sass 的差异

  1. 实现方式: Less 是基于 JavaScript 运行,所以 Less 是在客户端处理; Sass 是基于 Ruby 的,是在服务器端处理的。

  2. 变量: Less 使用@, Sass 使用$, Sass 在定义和使用时分别用到@mixin 和@include。

  3. 文件扩展: Less 后缀使用“.less”,   Sass 3.0 以前的版本后缀是“.sass”, Sass3.0 之后使用后缀‘scss’

  4. 语法差异, 上面已经列出,不再赘述。

4.有几种方式使用 Sass?

  • 作为命令行工具。

  • 作为独立的 Ruby 模块。

  • 作为任何启用了 Rack 的框架的插件。

5.有几种方式使用 Less?

  • 通过命令行。

  • 通过第三方工具。

  • 你可以下载 Less 作为浏览器的脚本文件。

6.Vue 项目中如何使用 Less/Sass?

  • npm/yarn 安装包

  • 在 webpack.config.js 中配置

{
    test: /\.less/,
    include: /node_modules/,
    loaders: ['style-loader', 'css-loader', 'less-loader'],
},
  • vue 文件中, 定义 lang 为 less, 或定义后缀为 less 的文件。

<style scoped lang="less"></style>

7.在 Less/Sass 中, extend 有什么用?

Less 中 extend 是其伪类, 用于在一个选择器中选择另一种选择器样式。 在 Sass 中, @extend 有相同功能。

//less
h2 {
   &:extend(.style);
   font-style: italic;
}
.style {
   background: green;
}
//CSS编译
h2 {
  background: green;
  font-style: italic;
}
//Sass
.message  {
  border: 1px solid #ccc
  padding: 10px
  color: #333
}
.success  {
  @extend .message
  border-color: green
}

8. Less/Sass 各有什么优点? (你会选择哪个)

Less 的优点:

  • Less 是一个 CSS 预处理器。编译后,它会生成简单的 CSS,适用于浏览器。

  • Less 支持跨浏览器兼容性。

  • 由于 Less 使用嵌套,使得代码更短、更干净,并以特定的方式组织

  • 由于 Less 使用变量,可以更快地实现维护。

  • Less 提供了一系列运算符,使编码更快,更省时。

  • Less 提供@mport 规则,这样我们就可以轻松地处理外部文件。注:导入是必需的,因为许多人将样式表分割为多个文件,而不是将其放入一个文件中。

  • Less 提供了合并属性。Less 最令人兴奋的特征是接受多个值,如 transform,transition 和 box-shadow。

  • Less 是用 JavaScript 编写的,它可以比 CSS 的其他预处理器更快地编译。

Sass 的优点:

  • Sass 提供了使用诸如循环, 条件之类的逻辑语句的便利, 还方便你编写可重用的方法。

  • Sass 的用户可以使用一些很棒的功能, 例如跨浏览器支持, 旧版浏览器黑客和动态 Sprite Map 生成。

  • Compass 还提供了添加外部框架(如 Bootstrap, Blueprint)的功能。

  • Sass 为你提供方便的功能编写工具。

9. CSS 优化、提高性能的方法有哪些?

(1)加载性能:

(1)css 压缩:将写好的 css 进行打包压缩,可以减少很多的体积。
(2)css 单一样式:当需要下边距和左边距的时候,很多时候选择:margin:top0bottom0;但 margin-bottom:bottom;margin-left:left;执行的效率更高。
(3)减少使用@import,而建议使用 link,因为后者在页面加载时一起加载,前者是等待页面加载完成之后再进行加载。

(2)选择器性能:

(1)关键选择器(keyselector)。选择器的最后面的部分为关键选择器(即用来匹配目标元素的部分)。CSS 选择符是从右到左进行匹配的。当使用后代选择器的时候,浏览器会遍历所有子元素来确定是否是指定的元素等等;
(2)如果规则拥有 ID 选择器作为其关键选择器,则不要为规则增加标签。过滤掉无关的规则(这样样式系统就不会浪费时间去匹配它们了)。
(3)避免使用通配规则,如*{}计算次数惊人!只对需要用到的元素进行选择。
(4)尽量少的去对标签进行选择,而是用 class。
(5)尽量少的去使用后代选择器,降低选择器的权重值。后代选择器的开销是最高的,尽量将选择器的深度降到最低,最高不要超过三层,更多的使用类来关联每一个标签元素。
(6)了解哪些属性是可以通过继承而来的,然后避免对这些属性重复指定规则。

(3)渲染性能:

(1)慎重使用高性能属性:浮动、定位。
(2)尽量减少页面重排、重绘。
(3)去除空规则:{}。空规则的产生原因一般来说是为了预留样式。去除这些空规则无疑能减少 css 文档体积。
(4)属性值为 0 时,不加单位。
(5)属性值为浮动小数 0.**,可以省略小数点之前的 0。
(6)标准化各种浏览器前缀:带浏览器前缀的在前。标准属性在后。
(7)不使用@import 前缀,它会影响 css 的加载速度。
(8)选择器优化嵌套,尽量避免层级过深。

推荐阅读:

  1. Sass 官方文档:https://www.sass.hk/docs/

  2. Less 官方文档:https://less.bootcss.com/#%E6%A6%82%E8%A7%88

  3. 104 道 CSS 面试题,助你查漏补缺
     


介绍一个在线编辑 Sass 的工具: Sassmeister

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值