Sass 基础 PXtoEMMixin 和 @function

发布于 2021-09-20 21:19:20 字数 9753 浏览 1486 评论 0

CSS 单位 是一个很意思的东西,到目前为止,CSS的单位不仅仅局限于 em,px,pt,com,in...,还出现了新的单位,比如 remvwvhvminvmax等等。在 CSS-trick 有对这些单位进行描述。在这么多的单位中,其中pxem两者的互转是最令同学们头痛的。简值是一言难尽,理不清呀!

如果你想了解更多有关于 pxem 相关知识,建议您仔细阅读一下下面的文章:

如果你理清楚了 px 和 em 之间的关系,那么你就可以使用 Em Calculator 工具,在线将 px 转成 em

看到上面的在线生成工具,我们应该回到今天我们要讨论的主题,如何使用 Sass 实现 px 转成 em。简单点说,使用 Sass 来实现 Em Calculator 工具功能。

CSS 中的 px 转 em

在 CSS 中 pxem,大家都有相当深的体会,特别是对于一些涉及这方面不深的同学,往往都被这两者折磨死了。如果您掌握了其中的绝巧,你就不会觉得复杂了。有的网友对此做过一些总结。

  • 浏览器的默认字体大小是 16px;
  • 不管元素有没有设置自身字体大小,元素自身上的所有属性值(box module相关的属性)都可以按照(1 ÷ 元素自身的font-size) × 需要转换的像素值 = em值。元素在没有设置自身font-size大小时,会直接继承其祖先元素的值;
  • 元素字体大小font-size的em按照如下公式计算(也就是font-size中的em值是相对于父元素的font-size值):(1 ÷ 父元素的font-size) × 需要转换的像素值 = em值

综合以上所述,我们可以简单的理解为:“默认1em=16px,而font-size使用em为单位时,是相对于其父元素(或祖先元素)的font-size;而元素其他属性(有关于box module,例如padding,border,width,height,margin等)使用em为单位时,是相对于元素本身的font-size值来计算。

知道如何使用公式将px转换成em,但在实际使用中,给我们的工作带来很多不便之处。特别是改变基本字体的时候,那你的噩梦就即将来了。或许你会说,我可以借助Em Calculator工具来完成。但这始终不是解决问题的最佳方案。

Sass 中的 px 转 em

我想使用 Sass 同学都会定义很多 mixins 运用于不同的项目中。我现在就在做这样的一件事情,将很多常用的公共样式模块抽取出来,分别定义成mixins,并且适用于每一个项目之中。今天将要做的也是类似于这样的一件事情。

有关于 Sass 中的 px 转 em 的代码片段到处可见,此处我们就不在纠结谁的代码优秀,谁的代码拙。我想我们应该了解他是怎么定义的,并且如何使用?

Sass 的 px 转 em 要点

使用Sass来实现pxem的计算,有几点需要注意:

  • pxem之间的计算原理(简单点说就是数学运算);
  • 需要定义一个函数,并且给其命名。

pxem 的计算

使用Sass来完成px转成em,其中第一步,也是非常关键的一步,需要明白两者之间怎么进行换算。前面我们也回忆了CSS中的pxem转换的计算。那么其原理同样可以运用到Sass中来。我们来看一个简单的例子。

假设置默认的字号font-size定义为16px,当你的标题一h1使用的字号为32px,此时,我们可以使用:

h1 {font-size: (32 / 16) * 1em}

//也就是

h1 {font-size: 2em;}

此时你可能会想,我们可以使用一个mixin来完成:

@mixin pxToem ($target-size,$context:$base-font-size){
    font-size: $target-size / $context;
}

@mixin pxToem实现了具体数字计算到变量计算的转换,也实现了最初示例所示的功能。但实际使用之中,pxem并不仅仅用在font-size属性,还有其他能使用长度单位的属性上。那上面的mixin离我们的目标还很遥远,我们应该继续的思考。

修改 px 转 em 的mixin

在GitHub上找到了一个功能强大的mixin,这个mixinDan Adams 两年前写的一个关于pxemmixin。这个mixin和Sass的一些Function有机的配合在一起,可以同是给多个属性,或者多个属性值进行pxem的计算。在这里,将其mixin名修改成了emCalc,主要出发点,就是便于大家可以更好的记忆。别的不多说,直接看代码:

$base-font-size: 16 !default;

@mixin emCalc($props,$sizes,$base:$base-font-size){
    $values: ();
    $sublists: false;

    @each $s in $sizes {
        //循环列表中多个属性值,例如text-shadow属性
        @if type-of($s) == list {
            $sublists: true;
            $vv: ();
            @each $ss in $s {
                $vv: append($vv,if(type-of($ss) == number, #{$ss / $base}em, $ss));
            }
            $values: append($values,join((), $vv));
        }
        @else {
            $values: append($values,if(type-of($s) == number, #{$s / $base}em, $s));
        }
    }
    $value: join((), $values, if($sublists,comma,space));
    @each $prop in $props {#{$prop}: $value}
}

看上去是不是很复杂呀。其实也没有大家想像的那么复杂,你只需要把Sass中的Function做一些了解,就好办了(我们后期会对Sass的Function做详细的介绍)。

我们还是回到emCalc上来。@mixin emCalc主要功能是对元素属性的px转换成em单位,而这个mixin具有一个更强大的功能,他可以同时给元素的多个属性,多个属性值或者同时多个属性多个属性值的px单位转换成em单位。不过在使用过程中,有一点也是非常重要的:emCalc中给参数$base传递的变量$base-font-size只能是数值,不能带有任何单位,包括需要转换的属性值中也不能含有任何单位

虽然 emCalc 的定义看上去复杂,但实际使用是很简单,简单的来看一段代码:

//SCSS
.header {
    @include emCalc(line-height, 30, 16);
    @include emCalc(width height, 125);
    @include emCalc(padding, 0 25, 16);
    @include emCalc(text-shadow, (#0d6e28 1 1) (#777 0 0 2), 16);
    @include emCalc(box-shadow, (inset 0 0 0 1 #2a9022) (inset 0 0 3 #459966), 16);
}

//CSS
.header {
  line-height: 1.875em;
  width: 7.8125em;
  height: 7.8125em;
  padding: 0em 1.5625em;
  text-shadow: #0d6e28 0.0625em 0.0625em, #777777 0em 0em 0.125em;
  box-shadow: inset 0em 0em 0em 0.0625em #2a9022, inset 0em 0em 0.1875em #459966; }

定义em计算函数

除了定义mixin来实现pxem转换之外,我们还可以考虑Sass的另一个方案。在Sass中提供了函数function的概念,可以通过创建一个函数为实现这样的计算。

//如果不覆盖,设置一个默认字体大小(以像素为单位)
$base-font-size: 16px !default;

//将px转换成em
//当元素的父元素没有重置字体大小时,相对于16px计算,如果你要将12px转换成em时,可以写成`pxToem(12px)`
//当元素的父元素重置了字体大小时,如24px,如果你要将12px转换成em时,可以写成`pxToem(12px,24px)`
//另外你还可以不显式的写也单位`px`

@function pxToem($target-size,$context:$base-font-size){
    @if not unitless($target-size){//unitless(12)=>true,unitless(12px)=>false
        $target-size: strip-units($target-size);//去掉 $target-size单位
    }
    @if not unitless($context){
        $context: strip-units($context);//去掉 $context单位
    }
    @return ($target-size / $context) * 1em;
}

pxToem()函数设置了两个参数,$target-size$context,并且给$context传递了一个参数值$base-font-size。而$base-font-size是一个变量值,一般用来定义html元素(根元素的字号,浏览器默认值为16px)。很多地方,有介绍,为了方便pxem之里计算,一般设置为10px

而且在pxToem()函数中,还使用了unitless()函数,用来判断传$target-size$context值是否带有单位。如果带有单位就为false,否则就为true

unitless(12);//输出值为`true`
unitless(12px);//输出值为`false`

这样一来,要是传给$target-size$context是带有单位的值,我们就需要做一个判断,才能进入后面的计算,这个时候就需要添加一个not来判断。

not unitless(12);//输出为`false`,跳过直接进入一行代码
not unitless(12px);//输出为`true`,做条件判断中程序处理

此时关键的时候又出现了,当传给$target-size或者$context的值带有单位时,我们需要做一件事情,将单位去掉。在上面的pxToem()函数中使用了strip-units()函数。可惜的是,在Sass中,并没有一个这样的函数,因此为了达到这个功能,需要自定义这个函数:

//去掉一个值的单位,如12px => 12
@function strip-units($number){
    @return $number / ($number * 0 + 1);
}

strip-units()pxToem()两个函数合并到一起,就实现了pxem的计算:

@function strip-units($number){
    @return $number / ($number * 0 + 1);
}

$base-font-size: 16px !default;

@function pxToem($target-size,$context:$base-font-size){
    @if not unitless($target-size){     
        $target-size: strip-units($target-size);    }
    @if not unitless($context){
        $context: strip-units($context);
    }
    @return ($target-size / $context) * 1em;
}

实际使用就非常简单了:

//SCSS
.header {
    font-size: pxToem(12);
    h1 {
        font-size: pxToem(12,24);
    }
}

.footer {
    margin: pxToem(12px);
    h1 {
        margin: pxToem(12px,24px);
    }
}

//CSS
.header {
  font-size: 0.75em; }
  .header h1 {
    font-size: 0.5em; }

.footer {
  margin: 0.75em; }
  .footer h1 {
    margin: 0.5em; }

总结

今天主要和大家探讨了如何使用Sass完成px转向em的功能。从简单的mixin开始,只为每个单独的属性服务,到复杂的mixin,同时实现多个属性、属性值的转换计算。并且还通过定义函数来完成两者之间的转换计算。

不管使用mixin还是function来实现pxem的单位计算,都将回到他的最初原理。换句话说,要完全理解使用Sass完成pxem,就得理解清楚CSS中两者的转换关系。而且通过上面教程的学习,对 Sass的function也会有一个初步的概念。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

泛泛之交

暂无简介

0 文章
0 评论
21557 人气
更多

推荐作者

遂心如意

文章 0 评论 0

5513090242

文章 0 评论 0

巷雨优美回忆

文章 0 评论 0

junpengz2000

文章 0 评论 0

13郎

文章 0 评论 0

qq_xU4RDg

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文