使用Sass减少重复性代码

来源:互联网 发布:大数据金融行业 编辑:程序博客网 时间:2024/05/21 14:02

Hugo大师在understand Sass lists和ADVANCED SASS LIST FUNCTIONS两篇文章中详细分析了Sass中list的功能,但在Sass中还有一个特性非常的有意思——变量插值。不管是列表,还是变量甚至说@if,@for,@each都是Sass中基础部分,仅从一个方面来看,并不能展示出Sass的魅力。反过来说,如果能将这几个部分结合在一起,那么将会给你的开发带来强大的方便性。今天我们就以Sass的变量作为话题的开端,来讨论Sass中变量配合其他功能另一用法。

在CSS的开发中,我们都在讨论OOCSS的使用,但其最终还是无法逃脱创建一些不使用的CSS代码。我们希望的是使用这些类产生的样式,需要的时候就产生CSS代码,不需要的时候就不产生CSS代码。希望做到的是真正按需生产,不产生额外的CSS代码。


来看一个典型的案例——Font Awesome图标制作,为了使用这个图标库里面的图标,在CSS的常规制作中,我们必须得将其样式导入进来。可是,很多时候,我们只需要其中的几个图标,换句话说,我只想给要的图标在样式中产生代码。在CSS中,我们无法实现,为了使用这个库,我们必须添加所有的图标类以及对应的相关代码。如此一来造成很多不需要的代码。

.icon-glass:before {  content: "\f000";}.icon-music:before {  content: "\f001";}.icon-search:before {  content: "\f002";}.icon-envelope-o:before {  content: "\f003";}.icon-heart:before {  content: "\f004";}.icon-star:before {  content: "\f005";}...

那么今天,我们就要来解决这个问题。

所需要的参数

欲解决上面提到的问题,我们在具体介绍详细的解决方案之前,我们需要一些参数。在Sass中,只要未调用,他是不会产生额外代码。此处我们主要借助Sass中的变量和列表来发力。

变量

大家都知道Font Awesome图标是通过字体来实现的,而其中每个图标都有其自身的实体编码,如"\f000""\f001"等等。当中就会有很多重复的代码,需要修复这些重复代码,我们就需要通过变量列表。首要条件是我们需要声明一些变量,我们把这些变量放在_variables.scss文件中。

$icon-glass: "\f000";$icon-music: "\f001";$icon-search: "\f002";$icon-envelope-o: "\f003";$icon-heart: "\f004";$icon-star: "\f005";

列表

接下来,我们需要一个列表,方便后面的遍历。注意,变量插值不能直接通过Sass的内部指令来控制。我想要一个带有选择器和名称和变量的列表,可在Sass中(至少目前为止)还不支持这样的特性。为了实现这样这一点,我们不得不对代码做一个变通。

$icon_names: icon-glass icon-music icon-search icon-envelope-o icon-heart icon-star;$icon_vars: $icon-glass $icon-music $icon-search $icon-envelope-o $icon-heart $icon-star;

解决方法

接下来,我们来看Sass中是如何解决这个问题,让你的代码在需要的时候产生。也就是说调用的时候就产生,不调用的时候不产生额外的CSS代码。本文主要通过以下几种方法来实现:

@each方法

第一种文案是采用Sass的列表遍历功能,使用变量$icon_names做类名遍历:

@each $name in $icon_names {    //在这进行操作}

这里使用了Sass的@each循环,在此处定义了一个新的变量$name。让变量$name$icon_names进行遍历。在我们的示例中,$name会遍历$icon_nam列表中的每个值。在此处一共会做五次遍历。

在循环中我们要添加一些动作,让$name变成我们需要的东西。简单点说,$name遍历的是$icon_names列表,每遍历一次就得到我们需要的一个类名,比如说.icon-glass。在接下的来的例子中,我们使用.#{$name}来得到类名。并且在其中添加样式:

@each $name in $icon_names {    .#{$name} {        content: $icon_vars;    }}

上面的循环中,我们通过$name变量的@each功能,使用$icon_vars得到需要的实体符。将上面的代码进行编译:

.icon-glass {  content: "\f000" "\f001" "\f002" "\f003" "\f004" "\f005"; }.icon-music {  content: "\f000" "\f001" "\f002" "\f003" "\f004" "\f005"; }.icon-search {  content: "\f000" "\f001" "\f002" "\f003" "\f004" "\f005"; }.icon-envelope-o {  content: "\f000" "\f001" "\f002" "\f003" "\f004" "\f005"; }.icon-heart {  content: "\f000" "\f001" "\f002" "\f003" "\f004" "\f005"; }.icon-star {  content: "\f000" "\f001" "\f002" "\f003" "\f004" "\f005"; }

很接近我们需要的,但我们每一个类只需要对应的一个实体符,因此我们还需要做一定的处理。在这里我们创建一个新的变量$i。Sass将通过index()函数,遍历$color_names中的$name,得到对应的索引值,并赋予给变量$i:

$i: index($icon_names, $name);

现在我们已经得到了索引号,我们可以使用这个值遍历这两个列表。使用Sass的nth()函数,我们可以指定一个列表,然后使用$i值,指定列表中的一个特定的值给CSS的content属性。

@each $name in $icon_names {    $i: index($icon_names, $name);    .#{$name} {        content: nth($icon_vars, $i);    }}

上面的意思就是,指定列表$icon_vars中第$i个值给contentn属性。我们来看一个编译出来的CSS:

.icon-glass {  content: "\f000"; }.icon-music {  content: "\f001"; }.icon-search {  content: "\f002"; }.icon-envelope-o {  content: "\f003"; }.icon-heart {  content: "\f004"; }.icon-star {  content: "\f005"; }

这就是我们需要的,但不是最理想的。

接下来,我们通过Sass的%placeholder@extend来创建一些占伴符。通过对%placeholder的介绍得知,%placeholder只是一个占位符,默认情况下是不产生任何CSS代码,这不正是我们想要的效果吗?

@each $name in $icon_names {    $i: index($icon_names, $name);    %#{$name} {        content: nth($icon_vars, $i);    }}

上面的代码编译后是得不到任何的CSS代码,要想上面的代码产生对应的CSS代码,我们需要在上面的代码基础上使用@extend扩展对应的%placeholder。在这个例子中,我们将看到再次遍历$icon_vars的值:

@each $name in $icon_names {    $i: index($icon_names, $name);    .#{$name} {        @extend %#{nth($icon_names, $i)};    }}

最终的代码:

$icon-glass: "\f000";$icon-music: "\f001";$icon-search: "\f002";$icon-envelope-o: "\f003";$icon-heart: "\f004";$icon-star: "\f005";$icon_names: icon-glass icon-music icon-search icon-envelope-o icon-heart icon-star;$icon_vars: $icon-glass $icon-music $icon-search $icon-envelope-o $icon-heart $icon-star;@each $name in $icon_names {    $i: index($icon_names, $name);    %#{$name} {        content: nth($icon_vars, $i);    }}@each $name in $icon_names {    $i: index($icon_names, $name);    .#{$name} {        @extend %#{nth($icon_names, $i)};    }}

编译出来的CSS:

.icon-glass {  content: "\f000"; }.icon-music {  content: "\f001"; }.icon-search {  content: "\f002"; }.icon-envelope-o {  content: "\f003"; }.icon-heart {  content: "\f004"; }.icon-star {  content: "\f005"; }

@for方法

在这个示例中,我们除了使用@each方法之外,还可以使用@for循环方法来处理。在@for循环的方法中,使用length()替代index()

@for $i from 1 through length($icon_names) {    %#{nth($icon_names, $i)} {        content: nth($icon_vars, $i);    }}@for $i from 1 through length($icon_names) {    .#{nth($icon_names, $i)} {        @extend %#{nth($icon_names, $i)};    }}

@function方法

$icon_vars可以通过创建一个函数功能进行查询。在我们的示例中,在$icon_vars中查询出对应的$icon_names对应的内容。

@function get-icon($search) {    $index: index($icon_names, $search);    @return nth($icon_vars, $index);}

在这个示例中,$search是我们在$icon_names查找的icon对应的类名。相对应函数返回的icon对应的实体符。我们可以使用一种简单的方法直接在函数中嵌套index()函数。

@function get-icon($search) {    @return nth($icon_vars, index($icon_names, $search));}

使用@function方法,同样在默认情况下是不会有任何的样式产生的,只有通过下面的方式调用的时候才会产生代码:

.icon-glass {    content: get-icon("icon-glass");}

编译出来的CSS:

.icon-glass {  content: "\f000"; }

这种方法才是我们真正想要的方式,真正叫按需产生。

除了上述的方法之外,我们还可以结合前面的知识做一个调整。

我可以单独的以key=>value的方式创建一个简单的Sass列表,例如:

$icons:    glass "\f000",    music "\f001",    search "\f002",    envelope-o "\f003",    heart "\f004",    star "\f005"    ;

同样,我们可以通过nth()函数功能,从$icons中检索中数字检索出对应的值:

.icon-glass {    content: nth($icons,1);}

编译出来的CSS:

.icon-glass {  content: glass "\f000"; }

这样的结果并不是我们需要的。为了解决这个问题,我们需要创建一个Sass函数,返回一个键名key和其对应的值value。也就是前面所说的key=>value所对应的效果:

@function get-icon($icon-name){    //$icons列表做循环    @each $icon in $icons {        //如果关键词key(第一个元素是当前的$icon)一样,参数指定返回的值        @if nth($icon, 1) == $icon-name {            @return nth($icon,2);        }    }}

现在,我们可以使用get-icon函数返回需要的值,达到按需产出:

.icon-glass {    content: get-icon(glass);}

编译出来的CSS:

.icon-glass {  content: "\f000"; }

最后列出,这种方法所使用的所有Sass代码:

$icons:    glass "\f000",    music "\f001",    search "\f002",    envelope-o "\f003",    heart "\f004",    star "\f005"    ;@function get-icon($icon-name){    @each $icon in $icons {        @if nth($icon, 1) == $icon-name {            @return nth($icon,2);        }    }}.icon-glass {    content: get-icon(glass);}
0 0
原创粉丝点击