简单讲讲sass中unit函数

语法

unit() 在 sass 中是一个内置函数,用于获取数值的单位。它返回一个字符串,表示数值的单位部分(如 pxrem% 等)。如果数值没有单位,则返回空字符串。

其语法如下:

unit($number)
  • 参数$number 是一个数值(带单位或不带单位)。
  • 返回值:数值的单位部分。

作用

获取单位

这是 unit() 最基本的用途,直接返回单位部分字符串。

$width: 100px;

unit($width) // 'px'

用于判断

配合 @if 可以来严格规定单位,使结果符合我们的预期。

例如:我们需要单位为 px,当传入 rem 单位时,报错。

@mixin set-margin($value) {
  @if unit($value) != "px" {
    @error "margin 的单位必须为 px, 但是传入了 `#{$value}`。";
  } @else {
    margin: $value;
  }
}

.box {
  @include set-margin(20px) // 正确
}

.error-box {
  @include set-margin(20rem) // 错误
}

然而在一些页面中,某些内容样式的单位需要使用 px 写死,而其他的一些内容需要使用相对单位,例如 rem% 等,我们就利用上述判断的方法,进一步扩展。

@mixin responsive-size($size) {
  $unit: unit($size);

  @if $unit == "px" {
    font-size: $size;
  } @else if $unit == "rem" {
    font-size: $size;
  } @else {
    @error "不支持的单位: `#{$unit}`。";
  }
}

.text {
  @include responsive-size(16px); // 正确
}

.head {
  @include responsive-size(2rem); // 正确
}

.error-text {
  @include responsive-size(10%); // 错误:不支持的单位: '%'。
}

编译结果

.text {
  font-size: 16px;
}

.head {
  font-size: 2rem;
}

单位转换

单位转换在实际开发中还是挺常用的,例如将 px 转为 rem ,我们就可以使用 unit() 配合一些运算来完成。

@function px-to-rem($px) {
  @if unit($px) != "px" {
    @error "字号单位必须为 px, 但是传入了 `#{$value}`。";
  }
  @return $px / 16 * 1rem;
}

.text {
  font-size: px-to-rem(32px); 
}

编译后得到

.text {
  font-size: 2rem;
}

案例

需求

我们需要开发一个响应式布局系统,要求:

  1. 支持多种设备类型(如 desktoptabletmobile)。
  2. 每种设备类型使用不同的单位(pxrem%)。
  3. 动态生成不同设备的样式。
  4. 如果传入的单位不符合要求,抛出错误提示。

实现

根据需求,先定义设备类型。我们使用 sass 中的 map

$devices: (
  desktop: px,
  tablet: rem,
  mobile: %
);

接下来,我们再定义一下转换函数并限制单位,将 px 转为 rem

@function px-to-rem($px) {
  @if unit($px) != "px" {
    @error "单位必须为 px,但是传入了 `#{$px}`。";
  }
  @return $px / 16 * 1rem;
}

然后,定义下 mixin

@mixin responsive-layout($property, $value, $device: "desktop") {
  // 获取设备对应的单位
  $expected-unit: map-get($devices, $device);

  // 检查设备类型是否有效
  @if not $expected-unit {
    @error "非法设备类型: `#{$device}`。";
  }

  // 获取传入值的单位
  $input-unit: unit($value);

  // 验证单位是否符合要求
  @if $input-unit != $expected-unit {
    @error "对于设备 #{$device}, #{$property} 值的单位必须是 #{$expected-unit}, 但是传入了 `#{$value}`。";
  }

  // 动态生成样式
  #{$property}: $value;
}

将定义好的 mixin 使用并验证下:

.container {
  @include responsive-layout(padding, 20px, "desktop"); // 正确
  @include responsive-layout(margin, 2rem, "tablet");   // 正确
  @include responsive-layout(width, 100%, "mobile");    // 正确
}

.error-container {
  @include responsive-layout(padding, 10%, "desktop"); // 错误
}

报错如下:

image

最后,借助 @each 遍历我们定义的设备类型,生成动态样式:

@each $device, $unit in $devices {
  .#{$device}-box {
    @include responsive-layout(
      padding,
      if($unit == "px", 20px, if($unit == "rem", 1.5rem, 100%)),
      $device
    );
  }
}

其编译结果如下:

.container {
  padding: 20px;
  margin: 2rem;
  width: 100%;
}

.desktop-box {
  padding: 20px;
}

.tablet-box {
  padding: 1.5rem;
}

.mobile-box {
  padding: 100%;
}

关于 unit() 今天就简单讲这么多,下课! :tieba_034:


已收录于 没啥用的CSS小知识!【更新中】

34 个赞

有目录 好评

1 个赞

鹅老师好 :tieba_087:

2 个赞

鹅佬课堂开课了

2 个赞

感谢教程

2 个赞

又双叒叕开课了

2 个赞

又双学css :tieba_095:

1 个赞

大鹅老师课堂又开课啦!

2 个赞

太强了,大鹅!

2 个赞

小水一手!

1 个赞

别的又不会,只有这样子才能维持水 :tieba_087:

2 个赞

太强了,大帅!

1 个赞

鹅老师小课堂又开课了

2 个赞


有这个真方便!感谢鹅佬

3 个赞

太强了!

2 个赞

太强了:tieba_087:大鹅老师tieba_025

2 个赞

好,以后也是邪字派了

2 个赞

这酒醒了
加上大鹅这句话
我才明天那天为啥那个谁说和大鹅一家了tieba_087

1 个赞

我宣布 你就是下一任無邪派掌门人

2 个赞

这升职加薪速度有点快、这就升职了tieba_073我还在蒙圈中……

4 个赞