欢迎光临
我们一直在努力

Less/Sass编译工具,koala使用指南

express阅读(49)

<

div class=”entry-content clearfix”>
如果你正在使用sass、less或coffee,而没有注意到koala,那说明你可能已经好久没有更新你的知识库了。koala这个由国人编写的,用于编译sass、less、coffee利器,在最近的短短几个月曝光率不亚于任何其他的技术。当然这跟其作者的辛勤劳动,让其更强更优秀有很大关系。在此先感谢koala的作者们,感谢你们给我们带来这么棒的免费工具。

其实编译工具有很多,我本人就各种免费的编译sass的工具都试过,一般都是不了了之,要么功能有限,要么编译速度不敢恭维,直到一个偶然的机会遇到koala,才停止搜索脚步,稳定使用它,现在它已经是我开机必备工具之一。下面我将以我自己的实际经验,简单介绍下koala。

选择koala的7大理由:

  1. 多语言支持:支持Less、Sass、CoffeeScript 和 Compass Framework。
  2. 实时编译:监听文件,当文件改变时自动执行编译,这一切都在后台运行,无需人工操作。
  3. 编译选项:既可统一设置文件的编译选项,也可单独设置某个文件的编译选项。
  4. 强大的文件右键功能:右键文件元素,即可操作打开文件,打开文件目录,打开输出文件目录,设置输出文件目录,编译,删除六大常用功能。
  5. 错误提示:在编译时如果遇到语法的错误,koala将在右下角弹出错误信息,方便开发者定位代码错误位置。
  6. 跨平台:windows、linux、mac都能完美运行。
  7. 免费且负责:koala完全免费,而且作者很负责,有什么问题作者都会及时给予答复,意见什么的可以直接提交给作者,一般在下一个版本就能得到解决。

了解了它的优点之后,我们来熟悉下它的界面,这个其实也是我选择它的一个原因。

简洁美观的面板


koala面板上面四个数字分别对应四个区域:

第一区域:第一个按钮用于添加项目,第二个按钮打开编译文件的错误提示,第三个按钮设置koala,里面可以设置所有文件默认的编译输出方式,需要过滤的文件,界面语言(中文/英文)等。当然这里也包括目前koala的版本号及作者等信息。

第二区域:project区域,可以直接把项目拖进该区域

第三区域:需编译的文件列表,默认以下划线开头的文件不出现列表中,绿色表示动态编译的文件,灰色表示非动态编译。单击相应的文件,出现第四个区块,设置文件编译的选项。如果你的文件是后添加的那么请点击上面的refresh按钮刷新需要编译的文件,当然也可以通过下面的几个all/less/sass/coffee来过滤自己要编译的文件。

第四区域:设置文件编译的选项,这个区域得选中第三个区域的某个需要编译的文件才会出现。以sass为例,第一个选项表示是否启用动态编译;第二组表示是否启用这四个功能,我这边为了方便调试所以启用debug info,当然如果你使用compass那就得启用compass;第三组表示输出的css格式,分为四种:nested,compressed,compact,expanded;最后一个compile按钮可以手动编译。

既然熟悉了界面,我们就实际使用下吧,步骤走起:

简单的使用步骤

第一步:首先点击我们第一区域的那个齿轮按钮,设置下默认文件的编译方式,并把界面语言设置为中文。


koala设置默认sass文件编译方式

koala设置中文界面第二步:添加我们要编译的项目文件,可通过第一区域的加号那个按钮添加,也可以直接将项目拖到第二个project区域。

第三步:单击我们需要编译的文件,出现第四区域设置下该文件具体的编译方式,如果没什么特别的,直接用默认设置的就ok,如果不需要动态编译,直接勾掉“即时编译”那个checkbox,其余的按照上面说的操作。


koala sass文件单击面板第四步:右键单击需要编译的文件,出现我们常用的几个操作:打开文件,打开文件目录,打开输出文件目录,设置输出文件目录,编译,删除。一般这里我们需要设置下我们输出文件的目录。


koala sass文件右键功能菜单第五步:如果你的文件既有less,sass还有coffee,那么就最好有必须点击下面的过滤条件,选择你要动态编译的文件,不然一锅煮头都大了。


koala 文件过滤教程走完,好了,就这么简单,没什么复杂的,自己动手试试吧。如果你有什么问题可以直接联系koala的作者@OKLain,或者加入koala的qq群229098395
<div

sass揭秘之变量

express阅读(65)

<

div class=”entry-content clearfix”>
因为文章内含有很多sass代码,如需自己动手查看编译结果,推荐使用sassmeister这款在线编译工具,方便你阅读学习。

刚开始sass的人,也许其最大的抱怨就是sass的变量了,尤其是那些了解less变量的,更是会说sass的变量做得不如less的变量好,less中有明显的全局变量和局部变量之分,但是到sass这边来,好像有点乱了,分不清了。其实不管sass的变量还是less变量都是有其设计的原理的,有着不一样的科学性,下面我们简单来了解下。

全局变量和局部变量

要了解sass或less的变量,有必要先了解下js的变量定义,先来一段js的代码:

var a = 1;
(function(){
 a = 5;
})();
console.log(a);//5

上面这段代码,匿名函数里面的a因为没有使用var关键字来定义,所以当我们在函数外打印a的时候,得到的是5,改变了一开始定义的1

var a = 1;
(function(){
 var a = 5;
})();
console.log(a);//1

而这段代码,匿名函数里面的a使用了var关键字来定义,所以当我们在函数外打印a的时候,得到的是1,一开始定义的值。

如果你明白了上面两个的区别,那下面就好办了,如果你还没有明白,那么建议先去看下js的变量申明。 也许你现在已经看出眉目了,其实sass的变量设计用的是上面两段代码中的第一段思想,即在局部不使用var来申明,而less用的是第二段思想,即局部使用var来申明,这就是很多人所说的为什么sass没有局部变量。我们来两段代码测试下:

sass版

$color:red;
p{
 $color:blue;
 color:$color;//blue
}
a{
 color:$color;//blue
}

less版

@color:red;
p{
 @color:blue;
 color:@color;//blue
}
a{
 color:@color;//red
}

简单总结下:如果全局申明了一个变量a,sass中如果使用到局部中是属于改变a的值,所以后来所有的都是改变之后的值;而less中使用到局部变量则属于在局部重新定义a的值,不影响其他地方。说到底,其实sass和less的变量其实都是js变量的表现形式,两者都有其科学性,只是设计思路不同而已。

当然说到这里,可能有人会说了,那sass就没有局部变量喽。其实不然,正确的说法应该是:在有全局变量的情况下,sass是没有局部变量的。意思是如果要看到sass的局部变量,请不要设置全局变量。代码为证:

p{
    $color:blue;
    color:$color;//blue
}
a{
    color:$color;//$color未定义
}

这是一个没有定义全局变量$color的例子,上面的p元素的color为blue,而a里面就会报错因为$color没定义,它没有获取到p元素里面定义的那个$color变量,这证明了其实sass同样存在局部变量,只是这个前提是得没有全局变量。

相信到这里,大家应该对sass的变量有所了解,不至于那么迷惑吧。下面我们再来两段代码:

p{
    $color:blue;
    color:$color;//blue

    a{
        color:$color;//blue
    }   
}

这一段代码中,a嵌套在p中,然后在p元素中定义了$color这个变量,a里面是可以访问到$color变量的。

p{
    $color:blue;
    color:$color;//blue

    a{
        $color:red;         
        color:$color;//red
    }

    background-color:$color;//red

    span{
        color:$color;//red
    }
}
div{
    color:$color;//$color未定义
}

估计这里有人迷惑了,我们来分析下吧:因为sass的代码是从上到下解析的,所以这段代码执行到p的color值的时候颜色是上面的blue色,然后由于我们在a中又改变了$color的值为红色,所以后面所有p元素范围内用到$color这个变量的都为红色,这反应到我们后来的bgcolor和span的color上面,而p元素之外还是未定义。

这里吐个槽吧,其实个人觉得正是由于这个,使得开发sass的小心定义变量,以避免污染;而less呢却刚好相反,估计到时候就是全局局部满天飞的情况,代码一团糟。你想选择哪种呢?

关于sass的全部变量和局部变量就说到这,既然这篇文章的标题说了是sass变量揭秘,光这全局变量和局部变量肯定是满足不了大家的胃口的,下面我们继续说下sass变量的另一个创新点,变量默认值。

变量默认值!default

可能很多人对这个不是很熟悉,或者觉得这个其实就是个幌子,挂羊头卖狗肉的家伙。其实不然,它的来头可不小,而且是非常的科学,我是佩服的五体投地,因为它从根本上解决了困扰我多年的css组件化开发。简单来两段比较的代码:

无!default

$color:red;
$color:blue;
p{
 color:$color;//blue
}

有!default

$color:red;
$color:blue !default;
p{
 color:$color;//red
}

上面说了,sass编译css是从上到下的,后面会覆盖前面的,所以第一段无!default的解析的是blue,而第二段代码由于有了!default,打破了这个规则,使用了前面定义的red。有意思吧,当然这样的使用是体现不了它伟大的价值的。

简单介绍下它的作用吧:假设变量申明带有!default,那么如果在此申明之前没有这个变量的申明,则用这个值,反之如果之前有申明,则用申明的值。当然如果你先!default申明,然后再申明一次,那就没什么意思了,这就是基本的变量覆盖,第一次申明的有无!default都一样。所以你要区分这两种情况:

//第一种,使用默认值 
//变量申明带有!default,但是之前没有这个变量的申明 
$color:blue !default; 
p{ color:$color;//blue }
//第二种,使用前面定义的值
$color:red; 
//变量申明带有!default,但是前面还有这个变量的申明
$color:blue !default;
p{
    color:$color;//red
}
//第三种错误的用法,先!default申明
$color:red !default;
$color:blue;

上面的第三种错误用法其实和下面的这个覆盖写法是一样一样的:

//覆盖写法
$color:red;
$color:blue;

能一口气看到这里的,应该有点时间,建议简单活动下,摇摇脑袋,伸伸懒腰,因为下面的更加精彩。

其实长久以来,css之所以不能组件化开发,有两大原因:第一个是@import的样式不能合并在一个文件中(这里排除使用压缩工具来合并);第二个问题就是这里说到的变量问题了。感谢sass帮我们全解决了,大笑三声。

现在假设我们有个scss文件,这里暂且叫做_imgstyle.scss,代码如下:

// 变量
//---------------------------------
$imgStyleBorder:         1px solid #ccc !default;
$imgStylePadding:        2px !default;
$imgStyleRadius:         8px !default;

// mixin
//---------------------------------
@mixin img-border($border:$imgStyleBorder,$padding:$imgStylePadding){
    border: $border;
    padding: $padding;
}

@mixin img-rounded($radius:$imgStyleRadius){
    border-radius:$radius;  
}

//样式
//---------------------------------
.img-border{
    @include img-border;
}

.img-rounded{
    @include img-rounded;
}

接下来我们要在style.scss这个文件里面调用_imgstyle.scss,代码如下:

//导入_imgstyle.scss
@import 'imgstyle';

现在问题来了,如果我们对默认的padding为2px不满意,要改为5px,我们有如下方法:

方法一:重新覆写

//导入_imgstyle.scss
@import 'imgstyle';
.img-border{
 padding:5px;
}

解析成的css:

.img-border {
 border: 1px solid #cccccc;
 padding: 2px;
}
.img-rounded {
 border-radius: 8px;
}
.img-border {
 padding: 5px;
}

方法二:改变@include的参数

//导入_imgstyle.scss
@import 'imgstyle';
.img-border{
 @include img-border($imgStyleBorder,5px);
}

解析成的css:

.img-border {
 border: 1px solid #cccccc;
 padding: 2px;
}
.img-rounded {
 border-radius: 8px;
}
.img-border {
 border: 1px solid #cccccc;
 padding: 5px;
}

显而易见,上面的方法都会产生重复的代码,不科学啊。当然这时候可能有人会说了,你脑子浸水了呗,直接在_imgstyle.scss文件中,修改$imgStyleBorder为5px不就得了。当然如果你要的是每个项目使用这个样式的时候都拷贝一份这个,然后打开把变量修改成你要的值,那么我只好承认我脑子浸水了,不仅脑子浸水,还得吐血了。

现在请上面那些山寨土鳖方法闪一边去,该我们的!default出场了,废话少说,上代码:

//申明$imgStylePadding为5px
$imgStylePadding: 5px;
//导入_imgstyle.scss
@import 'imgstyle';

解析成的css:

.img-border {
 border: 1px solid #cccccc;
 padding: 5px;
}
.img-rounded {
 border-radius: 8px;
}

无须去源文件中修改,且解析出来无重复代码,完美!这才是!default的价值,这为组件式开发,更改调用组件里面的变量的值带来了彻底的变化。如果less真没有这个变量的默认值的话,那less的同学们估计得伤心死了。

重量级的都介绍完了,下面把其他的一些小罗罗也简单介绍下吧。

变量后面加…

在css3出现以前,你是绝对没有看到过的,因为它就是为css3而设计的。css3在给css带来翻天覆地的变化之外,也给sass的@mixin传递参数带来纠结了。一般来说我们的@mixin传递的参数是以,来分隔的,但是css3的一些属性可以设置多个值,并且多个值以,分开,如box-shadow:0 0 3px rgba(0,0,0,0.3),inset 0 0 3px rgba(255,255,255,0.3);这让@mixin如何给box-shadow传递参数啊。所以这种变量后面加...的变量就出现了。

@mixin box-shadow($shadow...){
 -webkit-box-shadow:$shadow;
 -moz-box-shadow:$shadow;
 box-shadow:$shadow;
}

这样就完美解决了这个需求了,漂亮吧哈哈。注意这种变量加...的方式只出现在传递参数中,你可以看到上面的大括号里面的变量都是没有...。除了box-shadow,gradient也可以用,反正能使用多个值的属性里面都可以用。

变量用#{}包裹

一般来说,我们设置的变量都是用于属性值的,而如果用在属性或者选择器上,就得以#{}包裹起来了。

$btnClass: btn !default;
$borderDirection:  top !default;

.#{$btnClass}{
    border-#{$borderDirection}:1px solid #ccc;
}

解析成的css:

.btn{
 border-top:1px solid #ccc;
}

多个变量一起申明

其实这个还是很实用的,把多个相关的值写在一个变量里,然后通过nth($var,index)来获取第几个值。

$linkColor: red blue !default;

a{
    color:nth($linkColor,1);

    &:hover{
        color:nth($linkColor,2);
    }
}

解析成的css:

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

关于sass变量揭秘到此为止。如果你对sass比较感兴趣但是还不会,可以试试我们的sassGuide教程,如果已经开始使用sass了,欢迎试用sassCore这个库。
<div

sass揭秘之@if,@for,@each

express阅读(54)

<

div class=”entry-content clearfix”>
因为文章内含有很多sass代码,如需自己动手查看编译结果,推荐使用sassmeister这款在线编译工具,方便你阅读学习。

经过上两篇揭秘,大家心里对sass应该有了很好的认知感了,这篇文章基于前面两篇为基础,请确保你先浏览了前面的两篇文章,不然可能给你带来疑惑感觉。

  1. sass揭秘之变量
  2. sass揭秘之@mixin,%,@function

这篇文章关键是对sass判断或循环的语法熟悉下,至于逻辑这东西,和其他的语言如js,php什么的是一样一样的,没什么说头。经过前两篇的积累,也就不需要那么啰嗦了,所以只写scss代码。现在你就可以想想css如果用上这些东西会是什么样子的呢?

@if

这个@if就不用解释吧,一看都知道是条件判断。这个东西对于浏览器兼容这块可以出不少力量;然后对于写一些基础的scss,控制样式的输出也是一大利器;当然还有很多很多了,反正是个必备的好东西就是了。先来个简单的例子吧:

$lte7:true !default;//是否兼容ie6,7

//inline-block
//ie6-7 *display: inline;*zoom:1;
@mixin inline-block {
  display: inline-block;
  @if $lte7 {
    *display: inline;*zoom:1;
  }
}

如果变量$lte7为真,就输出*display: inline;*zoom:1;,这个例子看着有点熟悉吧,前面@mixin已经说了,哈哈。sass的东西其实也就是这么多,转来转去就转回来了。

既然有@if,那肯定有@else啊

$filter:false !default; //是否开启ie滤镜
//背景色半透明
@mixin bgcolor-alpha($bgcolor: rgba(0,0,0,.5)){
  color:#fff;
  @if $filter{
    filter:progid:DXImageTransform.Microsoft.gradient(enabled='true',startColorstr='#{ie-hex-str($bgcolor)}', endColorstr='#{ie-hex-str($bgcolor)}');
  }@else{
    background-color: #333;
  }
  background-color:$bgcolor;
}

这是半透明rgba背景的一段代码,高级浏览器用rgba,ie6-8如果开启滤镜用滤镜,不开启滤镜就用纯色,常用于图片下方浮现标题。至于多条件的,可以参考sass揭秘之@mixin,%,@function里面的神来之笔的@mixin prefixer

当然也不可能总是判断一个变量的真假那么简单,没有或与非的情况吧。sass的@if用not,or,and分别表示非,或,与。

$a:   false !default;
$b:   true !default;

@if not($a){
    p{
        color:red;
    }
}

div{
    font-size:14px;
    @if $a or $b{
        width:300px;
    }
}

li{
    line-height:24px;   
    @if $a and $b{
        float:left;
    }
}

想想还是漏了个,sass用==,!=分别表示等于与不等于。

$radius: 5px !default;

.box-border{
   border:1px solid #ccc;
   padding:10px;

   @if $radius != 0{
        border-radius:$radius; 
    }
}  

$sizeClass: small !default;

.size{
    @if $sizeClass == 'small'{
        padding:5px;
    }@else{
        padding:10px;
    }
}

是不是感觉很简单,本来就没什么特别的,判断和循环逻辑都是一样的,就是可能sass里面表现不一样吧。

@for

for循环有两种形式,分别为:@for $var from through 和@for $var from to 。$i表示变量,start表示起始值,end表示结束值,这两个的区别是关键字through表示包括end这个数,而to则不包括end这个数。先来个简单的:

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

上面的那个实例几乎用不着,哈哈所以其实是没什么营养的东西,只是帮助理解了原来@for是这么回事。怎么的也不能就这么忽悠大家啊,大家好不容易抽空看下文章,就这么点扯淡的东西怎么对得住呢。下面再来个营养级别的,@for应用在网格系统生成各个格子class的代码:

// class span1-$gridColumns
// span的class循环输出,通过变量$gridSpanSwitch来控制是否输出
//-----------------------------------------------------  
$gridColumns:      12 !default;
$gridcolumnWidth:  60px !default;
$gridGutter:       20px !default;

%span-base{
    float:left;
    margin-left:$gridGutter / 2;
    margin-right:$gridGutter / 2;
}
@for $i from 1 through $gridColumns {
    .span#{$i} {
        @extend %span-base;
        width:($gridcolumnWidth + $gridGutter) * $i - $gridGutter;
    }
}

解析后的css:

.span1, .span2, .span3, .span4, .span5, .span6, .span7, .span8, .span9, .span10, .span11, .span12 {
  float: left;
  margin-left: 10px;
  margin-right: 10px;
}
.span1 {
  width: 60px;
}
.span2 {
  width: 140px;
}
.span3 {
  width: 220px;
}
.span4 {
  width: 300px;
}
.span5 {
  width: 380px;
}
.span6 {
  width: 460px;
}
.span7 {
  width: 540px;
}
.span8 {
  width: 620px;
}
.span9 {
  width: 700px;
}
.span10 {
  width: 780px;
}
.span11 {
  width: 860px;
}
.span12 {
  width: 940px;
}

这样一循环,比一个个写爽多了吧,因为float和margin什么的都一样,所以我们使用占位选择器申明,然后@extend调用,那样就是组合申明了。当然如果你要一个更复杂的包括百分比和固定宽度切换的可以看下sassCore中的_grid.scss,这个网格系统就很强大了。

@each

语法:@each $var in

循环一个列表里面所有的值,然后去做点什么呗,那到底做点什么呢,这是个问题。你可以先想个三分钟试试,我们现在能用@each给css赋予什么魅力。

我来扯点其他的。其实@for和@each还是很少用的,但是只要它一上场,对于css来说一般都具有神来之笔,这就是要么不出手,一出手就震惊全场。

好了,插了上面一段后,我们来说说@each的官方实例:

@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'); 
}

上面是对icon class的定义,不过icon现在大家一般都用sprite去做,所以这种单独的很少了,不过可以同样用这个来设置background-position,假设这个sprite图片是宽30px,高120px,每个icon大小为30px*30px:

$sprite: puma sea-slug egret salamander !default;

%sprite-animal{
    background: url('/images/animal.png') no-repeat;
}
@each $animal in $sprite {
    .#{$animal}-icon {
        @extend %sprite-animal;     
        background-position:0 -(index($sprite,$animal)*30px);
    }
}

解析后的css:

.puma-icon, .sea-slug-icon, .egret-icon, .salamander-icon {
  background: url("/images/animal.png") no-repeat;
}

.puma-icon {
  background-position: -30px;
}

.sea-slug-icon {
  background-position: -60px;
}

.egret-icon {
  background-position: -90px;
}

.salamander-icon {
  background-position: -120px;
}

看起来还是比较帅的哈哈,但是sprite的图片有这么规整的还是很少的,现在有些网站搞sprite图片搞得太狠了,一般一个sprite那是包含各种大小的图片啊,不过这种网站如果维护频繁的话,那简直就是挖了天坑啊。

除了上面的sprite的运用,我们再来说个拍案叫绝的吧。自从bootstrap以后,框架遍地开花,而估计每个里面都会有的就是按钮的样式,而按钮的样式一般都要分颜色,大小吧,甚至按钮组。每个颜色一个class,每个大小还一个class,可是我们实际用的时候呢,估计能用个三分之一就不错了,反正最后就是那些定义好的按钮的样式远远超过了我们的需求,多大的浪费啊。

现在我们借用sass的@each就能帮我们控制这个问题,实用出发,需要什么就生成什么,不铺张不浪费。

//$btnColorClass: (primary #0078E7 #fff) (green $green #fff);
$btnColorClass: (primary #0078E7 #fff) (blue #00A3CF #fff) (orange #F47837 #fff) !default;

@mixin btn-color($bgColor:#e6e6e6, $textColor:#333){
    color:$textColor;
    background-color: $bgColor;
    border:1px solid darken($bgColor, 5%);
    border-color:lighten($bgColor, 2%) darken($bgColor, 5%) darken($bgColor, 5%) lighten($bgColor, 2%);

    &:hover{
        background-color: darken($bgColor,5%);
        color:$textColor;
    }
}

@each $colorClass in $btnColorClass{

  $class:      nth($colorClass,1);
  $bgColor:    nth($colorClass,2);
  $textColor:  nth($colorClass,3);

  .btn-#{$class}{
    @include btn-color($bgColor,$textColor);
  }
}

解析后的css:

.btn-primary {
  color: white;
  background-color: #0078e7;
  border: 1px solid #006bce;
  border-color: #007df1 #006bce #006bce #007df1;
}
.btn-primary:hover {
  background-color: #006bce;
  color: white;
}

.btn-blue {
  color: white;
  background-color: #00a3cf;
  border: 1px solid #008fb5;
  border-color: #00abd9 #008fb5 #008fb5 #00abd9;
}
.btn-blue:hover {
  background-color: #008fb5;
  color: white;
}

.btn-orange {
  color: white;
  background-color: #f47837;
  border: 1px solid #f3681f;
  border-color: #f57f41 #f3681f #f3681f #f57f41;
}
.btn-orange:hover {
  background-color: #f3681f;
  color: white;
}

轻松搞定,我们默认有三个颜色,现在如果我们要搞自己的颜色,直接按照第一篇sass揭秘之变量来重新定义下变量就ok了,这里你可以直接去掉那段注释//$btnColorClass: (primary #0078E7 #fff) (green $green #fff);就会解析成这两种class。现在你除了发表感叹“真牛B”之外,你也许还会想这是怎么出来的。不明觉厉啊。

下面详细展开下:

其实这里的核心就是$btnColorClass这个变量,也许你以前看到的就是一个变量对应一个值,如果你看了前面两篇文章,你会看到一个变量对应两个或多个值,而这里又升级了,对应了好多个啊,而且还是有组织的。简单来说这就跟js的数组差不多,相当于数组里面还有数组。

这里补充个知识,sass的列表值大致有三种形式分隔,分别为空格,逗号和小括号。空格比较常见,逗号还好了,我们说的第一个@each的官网案例,$list就是以逗号分隔的。

现在转回来,我们这个$btnColorClass,使用了两种分隔,空格和小括号,我们@each循环先得到用小括号分隔的,然后再在@each里面通过nth取得小括号里面用空格分开的列表值。说完了,就这么简单,突然发现把变量说完了,这个答案就解开了。

@if,@for,@each就算讲完了,当然还有一个@while,暂时还没太用它,也没什么特别的,所以就不说了,以后有用到绝妙之处再来说。

经过这三篇sass揭秘文章,大家对sass的了解也应该深入许多了,是不是发现它原来还有如此的迷人魅力。揭秘到这里,其实大家现在可以去分析下sassCore的源码了,其实这三篇文章里面好多东西都是从sassCore里面抽出来的,sassCore本身的代码比这些可能要复杂点,但是如果你对着三篇文章理解没问题的,sassCore源码也不会是问题,如有问题可在群中提问

sass揭秘暂时到此为止,休息一段时间,如果反响比较好的话,将继续为大家说下sass实战,包括给我以前写的那篇浅析sass死亡在团队合作中 文章一个答案。
<div

Sass基础——PX to EM Mixin和@function

express阅读(59)

<

div class=”entry-content clearfix”>
CSS单位是一个很意思的东西,到目前为止,CSS的单位不仅仅局限于em,px,pt,com,in…,还出现了新的单位,比如remvwvhvminvmax等等。在CSS-trick有对这些单位进行描述(可以点击这里阅读中文)。在这么多的单位中,其中pxem两者的互转是最令同学们头痛的。简值是一言难尽,理不清呀!

曾经在《CSS中强大的EM》一文中详细的介绍了px转成em的公式与使用细节,但只是仅仅看文字描述还是让人晕晕的,最好是动手写写。如果你想了解更多有关于pxem相关知识,建议您仔细阅读一下下面的文章:

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


Sass基础——PX to EM Mixin和@function

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

CSS中的pxem

在CSS中pxem,大家都有相当深的体会,特别是对于一些涉及这方面不深的同学,往往都被这两者折磨死了。如果您掌握了其中的绝巧,你就不会觉得复杂了。在《CSS中强大的EM》虽然在文中详细介绍了两者的转换的详细细节,文章相对蛮长的,或许有很多同学不喜欢阅读,有的网友对此做过一些总结。

  • 浏览器的默认字体大小是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中的pxem

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

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

Sass的pxem要点

使用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离我们的目标还很遥远,我们应该继续的思考。

修改pxem的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的概念(如果没有了解过的同学,可以先看看《sass揭秘之@mixin,%,@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也会有一个初步的概念。希望大家喜欢这篇教程,如果您有更好的意见或看法,欢迎一起探讨。
<div

Sass基础——Rem与Px的转换

express阅读(64)

<

div class=”entry-content clearfix”>
remCSS3中新增加的一个单位值,他和em单位一样,都是一个相对单位。不同的是em是相对于元素的父元素的font-size进行计算;rem是相对于根元素htmlfont-size进行计算。这样一来rem就绕开了复杂的层级关系,实现了类似于em单位的功能。

Rem的使用

前面说了em是相对于其父元素来设置字体大小的,这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小,在我们多次使用时,就会带来无法预知的错误风险。而rem是相对于根元素<html>,这样就意味着,我们只需要在根元素确定一个参考值,这个参考值设置为多少,完全可以根据您自己的需求来定。

假设就使用浏览器默认的字号16px,来看一些px单位与rem之间的转换关系:

|  px  |     rem       |
------------------------
|  12  | 12/16 = .75   |
|  14  | 14/16 = .875  |
|  16  | 16/16 = 1     |
|  18  | 18/16 = 1.125 |
|  20  | 20/16 = 1.25  |
|  24  | 24/16 = 1.5   |
|  30  | 30/16 = 1.875 |
|  36  | 36/16 = 2.25  |
|  42  | 42/16 = 2.625 |
|  48  | 48/16 = 3     |
-------------------------

如果你要设置一个不同的值,那么需要在根元素<html>中定义,为了方便计算,时常将在<html>元素中设置font-size值为62.5%:

html {
 font-size: 62.5%; /* 10 ÷ 16 × 100% = 62.5% */
}

相当于在<html>中设置font-size10px,此时,上面示例中所示的值将会改变:

|  px  |     rem        |
-------------------------
|  12  | 12/10 = 1.2    |
|  14  | 14/10 = 1.4    |
|  16  | 16/10 = 1.6    |
|  18  | 18/10 = 1.8    |
|  20  | 20/10 = 2.0    |
|  24  | 24/10 = 2.4    |
|  30  | 30/10 = 3.0    |
|  36  | 36/10 = 3.6    |
|  42  | 42/10 = 4.2    |
|  48  | 48/10 = 4.8    |
-------------------------

由于rem是CSS3中的一个属性,很多人首先关注的就是浏览器对他的支持度,我截了一张caniuserem属性的兼容表:


Sass基础——Rem与Px的转换

从上图可以清楚的知道,rem在众多浏览器中都已得到很好的支持,如果您的项目不用考虑IE低版本的话,你就可以放心的使用了,如果您的项目在IE低版本中还占有不少的比例,那么你还在担心使用rem不能兼容,而不敢使用。其实是没有必要的,可以针对低版本的IE浏览器做一定的处理:

html { font-size: 62.5%; } 
body { font-size: 14px; font-size: 1.4rem; } /* =14px */
h1 { font-size: 24px; font-size: 2.4rem; } /* =24px */

这样一来解决了IE低版本的不能兼容的问题,但生出另一个不足地方,就是增加了代码量。必竟鱼和熊掌很多时候不能兼得嘛。

如果你想更深入的了解rem如何使用,建议您阅读:

为什么要使用rem

em单位一样,在Responsive设计中使用rem单位非常有用。虽然他们都是相对单位,但使用rem单位可以避开很多层级的关系。因为em是相对于他的父元素的font-size,而rem是相对于根元素<html>。比如说h1设置了font-size1rem之后,只要不重置htmlfont-size大小,无论他的父元素设置多大,对h1都不会有任何的影响。

Sass中rem的使用

在CSS中,实现pxrem转换非常简单,但每次使用都需进行计算。虽然在html中设置font-size:62.5%;会给大家带来便利,但终究有些烦人,也不是长远之计。既然我们学习了Sass,就应该思考如何让Sass来帮助我们做这些计算的工作。接下来介绍如何使用Sass实现pxrem之间的计算。

rem@function中的使用

Sass中也可以像使用em一样,实现px转换为rem。这个过程也同样是通过Sass的@function方法来实现。

根据rem的使用原理,可以知道pxrem需要在html根元素设置一个font-size值,因为rem是相对于html根元素。在Sass中定义一个pxrem的函数,先要设置一个默认变量:

$browser-default-font-size: 16px !default;//变量的值可以根据自己需求定义

而且需要在html根元素中显示的声明font-size

html {
 font-size: $browser-default-font-size;
}

然后通过@function来实现px转为rem计算:

@function pxTorem($px){//$px为需要转换的字号
 @return $px / $browser-default-font-size * 1rem;
}

定义好@function之后,实际使用中就简单多了:

//SCSS
html {
    font-size: $browser-default-font-size;
}
.header {
    font-size: pxTorem(12px);
}

//CSS
html {
  font-size: 16px; }

.header {
  font-size: 0.75rem; }

不过定义的这个函数pxTorem()虽然实现了px转换成rem的计算,但不能同时服务于多个属性值的计算:

.header {
 font-size: pxTorem(12px);
 margin: pxTorem(5px 10px);//同时计算多个值将报错
}

如果这样使用,编译的时候将会报错:

>>> Change detected to: /Users/airen/Sites/testSass/style.scss
      error style.scss (Line 4: Undefined operation: "5px 10px/16px times 1rem".)

这也就是说,如果样式同时需要设置多个属性值的时候,pxTorem()变得就局限性太大,换句话说,这个函数仅适合运用在具有单个属性值的属性上,例如font-size。如果要强行使用,只能同时使用多个pxTorem()

//SCSS
.header {
    font-size: pxTorem(12px);
    margin: pxTorem(5px) pxTorem(10px) pxTorem(15px);
    border: pxTorem(1px) solid #f36;
}

//CSS
.header {
  font-size: 0.75rem;
  margin: 0.3125rem 0.625rem 0.9375rem;
  border: 0.0625rem solid #ff3366; }

Sass中mixin实现rem

除了使用@function实现px转换成rem之外,还可以使用Sass中的mixin实现pxrem功能。

font-size是样式中常见的属性之一,我们先来看一个简单mixin,用来实现font-sizepxrem

@mixin font-size($target){
 font-size: $target;
 font-size: ($target / $browser-default-font-size) * 1rem;
}

在实际使用中,可以通过@include调用定义好的@mixin font-size:

//SCSS
.footer {
    @include font-size(12px);
}

//CSS
.footer {
  font-size: 12px;
  font-size: 0.75rem; }

可实际中,这个mixin太弱小了,根本无法实现我们需要的效果,因为我们很多样式属性中他可不只一个属性。为了实现多个属性能设置多值,就需要对mixin做出功能扩展:

@mixin remCalc($property, $values...) {
  $max: length($values);//返回$values列表的长度值
  $pxValues: '';
  $remValues: '';

  @for $i from 1 through $max {
    $value: strip-units(nth($values, $i));//返回$values列表中的第$i个值,并将单位值去掉
    $browser-default-font-size: strip-units($browser-default-font-size);
    $pxValues: #{$pxValues + $value * $browser-default-font-size}px;

    @if $i < $max {
      $pxValues: #{$pxValues + " "};
    }
  } 

  @for $i from 1 through $max {
    $value: strip-units(nth($values, $i));
    $remValues: #{$remValues + $value}rem;

    @if $i < $max {
      $remValues: #{$remValues + " "};
    }
  } 

  #{$property}: $pxValues; 
  #{$property}: $remValues; 
}

在这个remCalc()中定义了两个参数$property$values...。其中$property表示的是样式属性,而$values...表示一个或者多个属性值。

注:在上面定义的remCalc中使用了下自定义的函数strip-units,主要用来去除单位,详细的请参阅Sass基础——PX to EM Mixin和@function一文中的strip-units函数定义方法。

pxremmixin定义完成后,就可以通过@include来引用:

//SCSS
.wrapper {
    @include remCalc(width,45);
    @include remCalc(margin,1,.5,2,3);
}

//CSS
.wrapper {
  width: 720px;
  width: 45rem;
  margin: 16px 8px 32px 48px;
  margin: 1rem 0.5rem 2rem 3rem; }

在实际使用中取值有一点非常重要remCalc()取的$values值为rem

总结

在这篇文章中,简单介绍了在Sass中如何定义@function@mixin来实现px转换成rem的计算。希望大家能在这篇文章中找到自己需要的灵感。
<div

Sass基础——颜色函数

express阅读(43)

<

div class=”entry-content clearfix”>
色彩是设计的一个美妙元素和一个至关重要的工具,同时他能帮助你更好的抓住您的客户。更为重要的是,色彩能帮你表达某些特定的情感,把用户视线带到特点的地方或者帮助你传达信息。在Web设计中,主要依靠颜色来表达你的色彩。

如果你只是直接丢一堆颜色给用户,他们也不会集中注意力在你的设计上的。色彩很微妙,所以为了让色彩成为可被利用的工具我们必须正确使用它。像其他设计元素一样,色彩也要好好利用才能发挥它的魔力。

但实际中,仅依靠CSS常用的颜色功能并不能迅速帮我们锁定需要的颜色。特别在很多时候,设计师在设计图中并没有明显标注某个控件其他状态颜色值时,我们不得不依靠设计工具,获取相近色。可这种方法并不是理想方法,很多时候让你的颜色(特别对颜色不感冒的同学)偏离你的产品,直接让你无法抓住你的客户。

虽然这样的工作可以依靠工具完成,但对于一位码农来说,不停的在工具之间进行切换,真心的是蛋疼。为了让你今后不在蛋疼,Sass给我们提供了多种颜色函数,帮助大家快速,准确获取相应的颜色。

Sass的颜色函数

在Sass的官方文档中,列出了Sass的颜色函数清单,从大的方面主要分为RGBHSLOpacity三大类函数,当然其还包括一些其他颜色函数,比如说adjust-colorchange-color等等。

RGB颜色函数

rgb颜色只是颜色中的一种表达方式,其中R是“red”表示红色,而G是“green”绿色,B是“blue”蓝色。在Sass中为RGB颜色提供六种函数:

仅从概念上,或许大家没有太多的概念,我们通过下面的命令来做一个简单的测试:

$ sass -i //在终端运行这个命令,开启Sass的函数计算

接下来,分别在终端使用RGB函数来进行计算,看其最终结果:

$ sass -i
>> rgb(200,40,88) //根据r:200,g:40,b:88计算出一个十六进制颜色值
#c82858
>> rgba(#c82858,.65) //根据#c82858的65%透明度计算出一个rgba颜色值
rgba(200, 40, 88, 0.65)
>> red(#c82858) //从#c82858颜色值中得到红色值200
200
>> green(#c82858) //从#c82858颜色值中得到绿色值40
40
>> blue(#c82858) //从#c82858颜色值中得到蓝色值88
88
>> mix(#c82858,rgba(200,40,80,.65),.3) //把#c82858和rgba(200,40,88,.65)两颜色按比例混合得到一个新颜色
rgba(200, 40, 80, 0.65105)

从上面的简单运算结果可以很清晰的知道。在RGB颜色函数中,在实际中常用的主要是rgba()mix()两个函数,而rgb()函数只能快速的将一个rgb颜色转换成十六进制颜色表达,red()green()blue()函数,只能取得某一颜色的一个值,对于颜色上使用并无太大作用(或许他的好处,我还没有理解过来)。接下来,主要来实战一下rgba()mix()函数在实际中的运用。

RGBA()函数

rgba()函数主要用来将一个颜色根据透明度转换成rgba颜色。其语法有两种格式:

rgba($red,$green,$blue,$alpha)//将一个rgba颜色转译出来,和未转译的值一样
rgba($color,$alpha) //将一个Hex颜色转换成rgba颜色

其中rgba($color,$alpha)函数作用更大,主要运用在这样的情形之中。假设在实际中知道的颜色值是#f36或者red,但在使用中,需要给他们配上一个透明度,这个时候在原来的CSS中,首先需要通过制图工具,得到#f36red颜色的RGB值,而不能直接使用:

//CSS
color: rgba($f36,.5);//这是无效的写法

但在Sass中,RGBA()函数就能解决这个问题。我们先来看一个简单的例子,假设在变量中定义了一个基本的变量:

$color: #f36;
$bgColor: orange;
$borderColor:green;

同时给他们加上.65的透明度:

//SCSS
.rgba {
 color: rgba(#f36,.5);
 background: rgba(orange,.5);
 border-color: rgba(green,.5);
}

在这个实例中,我们使用了Sass的rgba函数,在括号是函数的参数,第一个参数是需要转换的颜色,他可以是任何颜色的表达方式,也可以是一个颜色变量;第二个参数是颜色的透明度,其值是0~1之间。上面的代码转译出来:

.rgba {
 color: rgba(255, 51, 102, 0.5);
 background: rgba(255, 165, 0, 0.5);
 border-color: rgba(0, 128, 0, 0.5);
}

在来看一个调用前面定义的变量:

 

//SCSS
.rgba {
    color: rgba($color,.5);
    background: rgba($bgColor,.5);
    border-color: rgba($borderColor,.5);
}

//CSS
.rgba {
  color: rgba(255, 51, 102, 0.5);
  background: rgba(255, 165, 0, 0.5);
  border-color: rgba(0, 128, 0, 0.5);
}

我想您应该会看到一个变化,通过rgba函数,指定一个透明值,将原色转换成另外一个颜色:


Sass基础——颜色函数

Mix()函数

Mix函数是将两种颜色根据一定的比例混合在一起,生成另一种颜色。具体地说,选择权重是每个RGB的百分比来衡量,当然透明度也会有一定的权重。其中指定的比例会包括在返回的颜色中。默认的的比例是50%,这意味着两个颜色各占一半,如果指定的比例是25%,这意味着第一个颜色所占比例为25%,第二个颜色所占比例为75%。其使用语法如下:

mix($color-1,$color-2,$weight);

$color-1$color-2指的是你需要合并的颜色,颜色可以是任何表达式,也可以是颜色变量。$weight合并的比例,默认值为50%,其取值范围是0~1之间。

其使用方法也很简单:

mix(#f00, #00f) => #7f007f
mix(#f00, #00f, 25%) => #3f00bf
mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75)

在前面的基础上,做一个修改:

//SCSS
$color1: #a63;
$color2: #fff;
$bgColor1: #f36;
$bgColor2: #e36;
$borderColor1:#c36;
$borderColor2:#b36;

.mix {
    background: mix($bgColor1,$bgColor2,.75);
    color: mix($color1,$color2,.25);
    border-color: mix($borderColor1,$bgColor2,.05);
}

//CSS
.mix {
    background: #ee3366;
    color: #fefefe;
    border-color: #ed33
}

看下对比效果:


Sass基础——颜色函数

这就是Mix函数的工作原理,在函数中指定三个函数,前两个函数是你想混合的颜色(记住,你可以通过颜色变量、十六进制、RGBA、RGB、HSL或者HSLA颜色值)。第三个参数是第一种颜色的比例值。

HSL颜色函数

HSL给我们带来了一个更直观的颜色控制,我们时常需要让一个颜色比另一个颜色更暗一点或者说更亮一点。比如说“a:hover”状态下我们需要把一个颜色变暗一点,那么使用“HSL”是非常方便的,反而我们使用十六进制那就需要更多的时间调试。而这个“HSL”他只是一个简单的数量变化。

“HSL”所表示的是“H:色相”,“S:饱和度”,“L:亮度”。色相是在色盘上的颜色(见下图),颜色的选择是使用饱和度:“0度是红色”,“120度为绿色”和“240度为蓝色”。


Sass基础——颜色函数在看一个在线的HSL工具,会有更好的理解:


Sass基础——颜色函数

虽然这些工具都很优秀,但我们今天要讨论的是Sass函数。在Sass中提供了一系列有关于HSL的颜色函数,以供大家使用,其中常用的有saturationlightnessadjust-huelightendarken等等。接下来我们先来了解一下HSL颜色函数包括哪些具体的函数,所起的作用是什么。

同样在你的终端,通过sass -i来对上面的各个函数做一个简单测试:

>> hsl(200,30%,60%) //通过h200,s30%,l60%创建一个颜色
#7aa3b8
>> hsla(200,30%,60%,.8)//通过h200,s30%,l60%,a80%创建一个颜色
rgba(122, 163, 184, 0.8)
>> hue(#7ab)//得到#7ab颜色的色相值
195deg
>> saturation(#7ab)//得到#7ab颜色的饱和度值
33.33333%
>> lightness(#7ab)//得到#7ab颜色的亮度值
60%
>> adjust-hue(#f36,150deg) //改变#f36颜色的色相值为150deg
#33ff66
>> lighten(#f36,50%) //把#f36颜色亮度提高50%
#ffffff
>> darken(#f36,50%) //把#f36颜色亮度降低50%
#33000d
>> saturate(#f36,50%) //把#f36颜色饱和度提高50%
#ff3366
>> desaturate(#f36,50%) //把#f36颜色饱和度降低50%
#cc667f
>> grayscale(#f36) //把#f36颜色变成灰色
#999999
>> complement(#f36) 
#33ffcc
>> invert(#f36)
#00cc99

在HSL函数中,hsl()hsla()函数主要是通过颜色的HSL或者A几个参数获取一个rgbrgba表达的颜色,这两个函数与CSS中的无太大区别,只是使用这两个函数能帮助您知道颜色的十六进制表达式和rgba表达式。

hue()saturation()lightness()函数主要是用来获取指定颜色中的色相值、饱和度和亮度值。对于颜色表达没有太多的实际作用。

HSL函数中最常见的应该是lighten()darken()saturate()desaturate()grayscale()complement()invert()几个函数。接下来,我们针对这几个函数来做进一步的了解与学习。

lighten() & darken()函数

lighten()darken()两个函数都是围绕颜色的亮度值做调整的,其中lighten()函数会让颜色变得更亮,与之相反的darken()函数会让颜色变得更暗。这个亮度值可以是0~1之间,不过常用的一般都在3%~20%之间。

来看一个简单的实例,首先定义一个颜色变量:

$baseColor: #ad141e;

使用lighten()darken()函数来修改10%的亮度值:

//SCSS
.lighten {
    background: lighten($baseColor,10%);
}
.darken{
    background: darken($baseColor,10%);
}

//CSS
.lighten {
  background: #db1926; 
}

.darken {
  background: #7f0f16; 
}


Sass基础——颜色函数

从效果中,明显看出颜色之间的差异,我们使用函数lightness()函数来验证一下三个颜色之间亮度值的变化:

>> lightness(#ad141e) //原色的亮度值
37.84314%
>> lightness(#db1926) //在原色的亮度值基础上增加10%
47.84314%
>> lightness(#7f0f16) //在原色的亮度值基础上减少10%
27.84314%

lighten()darken()函数只是在原始颜色的基础上对亮度值进行运算操作,但是生成出来的新颜色在色相和饱和度会有略微的变化,比如上面的实例生成的新颜色与原始色在色相与饱和度值的对比:

>> hue(#ad141e)
356.07843deg
>> hue(#db1926)
355.97938deg
>> hue(#7f0f16)
356.25deg
>> saturation(#ad141e)
79.27461%
>> saturation(#db1926)
79.5082%
>> saturation(#7f0f16)
78.87324%

如果有点颜色概念基础的同学应该都清楚,不管什么颜色当其亮度值趋近于0时,颜色会越来越暗,直到变成了黑色;反之,当其亮度值趋近于100%时,颜色会越来越亮,直到变成了白色。但当使用lighten()darken()函数对一个颜色的亮度值计算时,会碰到两个极端,lighten()函数会让新颜色的亮度值超过100%,而darken()函数会让新颜色的亮度值低于0变成负数。可实际上任何颜色的亮度值都在0~100%之间,如此一来,Sass的lighten()darken()函数又将会如何处理呢?

带着上面的疑问,我们一起来做一个简单性的测试。从上面的示例中得知#ad1414的亮度值为37.84314%,为了让新颜色的亮度值大于100%和小于0,在对应的函数,做一些调整:

//SCSS
.lighten {
    background: lighten($baseColor,70%);
}
.darken{
    background: darken($baseColor,40%);
}

//CSS
.lighten {
  background: white; 
}

.darken {
  background: black; 
}

上面的例子说明了一切问题。当颜色的亮度值接近或大于100%,颜色会变成白色;反之颜色的亮度值接近或小于0时,颜色会变成黑色。

saturate() & desaturate()函数

这两个函数是通过改变颜色的饱和度来得到一个新的颜色,他们和前面介绍的修改亮度得到新颜色的方法非常相似。

//SCSS
.saturate {
  background: saturate($baseColor,30%);
}
.desaturate {
  background: desaturate($baseColor,30%);
}

//CSS
.saturate {
  background: #c1000d; 
}

.desaturate {
  background: #903137; 
}


Sass基础——颜色函数

颜色变了。同样使用saturation()函数在终端中进行计算一下,看看他们有起了什么样的变化:

>> saturation(#ad141e) //原色的饱和度
79.27461%
>> saturation(#c1000d) //在原色饱和度基础上增加30%,超过100%时按100%计算
100%
>> saturation(#903137) //在原色饱和度基础上减少30%,小于0时按0计算
49.2228%

adjust-hue()函数

这个是通过调整颜色的色相换算一个新颜色。他需要一个颜色和色相度数值。通常这个度数值是在-360deg360deg之间,当然了可以是百分数:

//SCSS
.adjust-hue-deg {
  background: adjust-hue($baseColor,30deg);
}
.adjust-hue-per {
  background: adjust-hue($baseColor,30%);
}

//CSS
.adjust-hue-deg {
  background: #ad5614; 
}

.adjust-hue-per {
  background: #ad5614;
}


Sass基础——颜色函数

从转译出来的代码,不难发现他们的颜色是一样的。尝试多次,如果两个值(抛弃deg100%)相同,计算出来的颜色也会一样。

同样的,可以通过hue()函数得到颜色转换前后的色相值:

>> hue(#ad141e) //原颜色色相值
356.07843deg
>> hue(#ad5614) //在原色色相基础上增加30deg
25.88235deg

这里有一个很有意思的地方,在HSL颜色表达方式上,色相是从-360360之间,负值逆时针转,正值顺时针转。在这个实例中,原色的色相值约356deg,加上30deg后,新颜色变成了386deg,但我们的色盘中并没有比360deg更大的值,此时新颜色的值也并不会是386deg,那将怎么办呢?其实很简单,当值大于360deg时,表示色盘转完了一圈,继续顺时针转余下的值(这里是26deg),那么这个继续转的值就是新颜色的色相值。小伙伴们,看到这个,你是不是又有点惊了。反之,得到的负数值也是一样的道理。

grayscale()函数

这个函数会颜色的饱和度值直接调至0%,所以此函数与desaturate($color,100%)所起的功能是一样的。一般这个函数能将彩色颜色转换成不同程度的灰色。例如:

//SCSS
.grayscale {
  background: grayscale($baseColor);
}
.desaturate {
  background: desaturate($baseColor,100%);
}

//CSS
.grayscale {
  background: #616161; 
}

.desaturate {
  background: #616161; 
}


Sass基础——颜色函数

看看计算出来的HSL各个值的变化:

>> hue(#ad141e)
356.07843deg
>> hue(#616161)
0deg
>> saturation(#ad141e)
79.27461%
>> saturation(#616161)
0%
>> lightness(#ad141e)
37.84314%
>> lightness(#616161)
38.03922%

结过grayscale()函数处理过的颜色,其最大的特征就是颜色的饱和度为0。

complement()函数

complement()函数也是非常的神奇,可以在原色上得到一个补充色。这个函数与adjust-hue($color,180deg)取得的效果是一样的。如:

//SCSS
.complement {
  background: complement($baseColor);
}
.adjust-hue {
  background: adjust-hue($baseColor,180deg);
}

//CSS
.complement {
  background: #14ada3; 
}

.adjust-hue {
  background: #14ada3; 
}


Sass基础——颜色函数

颜色变换前后的参数变化对照:

>> hue(#ad141e)
356.07843deg
>> hue(#14ada3)
176.07843deg
>> saturation(#ad141e)
79.27461%
>> saturation(#14ada3)
79.27461%
>> lightness(#ad141e)
37.84314%
>> lightness(#14ada3)
37.84314%

很明显,complement()函数就是让原颜色的色相减去180deg,得到的新值就是新颜色的色相值,而新旧颜色的饱和度和亮度值,并没有任何的差异。

invert()函数

invert()函数也是一个神奇的函数。根据颜色的RGB单独进行反相,然后合并到一起,当然其中的透度值A也可以结合进来。

首先们来看一个示例:

//SCSS
$baseColor1: #ad141e;
$baseColor2: #d90fec;

.invert1 {
  background: invert($baseColor1);
}
.invert2 {
  background: invert($baseColor2);
}

//CSS
.invert1 {
  background: #52ebe1; 
}

.invert2 {
  background: #26f013; 
}


Sass基础——颜色函数

通过函数实现非常简单,大家更想知道的是这个反相是如何出来的。如果你要是感兴趣,可以仔细阅读一下这个反相计算的原理。

首先,我们常见的颜色十六进制表达方式中,能看到表达颜色的数字为0~9,字母为a~f而其中a~f我们可以理解为对应的数字为10~15:

1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - a(10) - b(11) - c(12) - d(13) - e14 - f(15)

而我们的颜色对应的是:

|--------|--------|--------|--------|
|        |   R    |    G   |   B    |
|--------|--------|--------|--------|
|   原色  |   ad   |   14   |   1e   |
|--------|--------|--------|--------|
|  反相色 |   52   |    eb  |   e1   |
|--------|--------|--------|--------|

继续拆分:

|--------|----|----|----|----|----|----|
|        | r1 | r2 | g1 | g2 | b1 | b2 |
|--------|----|----|----|----|----|----|
|  原色    | y1 | y2 | y3 | y4 | y5 | y6 |
|--------|----|----|----|----|----|----|
|  反相色 | i1 | i2 | i3 | i4 | i5 | i6 |
|--------|----|----|----|----|----|----|

接下来做一个加法运算:

r1 = y1 + i1 = 15 = F
r2 = y2 + i2 = 15 = F
g1 = y3 + i3 = 15 = F
g2 = y4 + i4 = 15 = F
b1 = y5 + i5 = 15 = F
b2 = y6 + i6 = 15 = F

基中y代表的是原色中的各色值位置,i代表反相色各色值位置,例如这里,对应的y1~y6值分别为:

原色 => $baseColor1 => #ad141e
y1 = a => y1 = 10
y2 = d => y2 = 13
y3 = 1
y4 = 4
y5 = 1
y6 = e => y6 = 14

根据前面总结的公式,就可以轻松的算出反相色各位置的值:

i1 = 15 - y1 = 15 - 10 = 5
i2 = 15 - y2 = 15 - 13 = 2
i3 = 15 - y3 = 15 - 1 = 14 => e
i4 = 15 - y4 = 15 - 4 = 11 => b
i5 = 15 - y5 = 15 - 1 = 14 => e
i6 = 15 - y6 = 15 - 14 = 1

在把得出的颜色值进行合并,得出颜色值为#52ebe1,与转译出来的颜色刚好稳合。根据同样的方法,可以将第二个颜色#d90fec的反相色计算出来:

i1 = 15 - y1 = 15 - d = 15 - 13 = 2
i2 = 15 - y2 = 15 - 9 = 6
i3 = 15 - y3 = 15 - 0 = 15 => f
i4 = 15 - y4 = 15 - f = 15 - 15 = 0
i5 = 15 - y5 = 15 - e = 15 - 14 = 1
i6 = 15 - y6 = 15 - c = 15 - 12 = 3

那么根据计算出来,得到的反相颜色为#26f013。和使用函数转译出来的值是一样的。

如果你的颜色带有一个透明度参数,比如说是一个rgba颜色,那么通过invert()函数转换出来的新颜色,并不会对颜色中的透明度值a做任何的计算,他们保持不变,仅到RGB值做计算。

 

//SCSS
$baseColor: rgba(20,30,40,.7);

.invert {
  background: invert($baseColor);
}

//CSS
.invert {
  background: rgba(235, 225, 215, 0.7); 
}

通过这个实例,大家还可以根据RGB颜色值方法来进行计算,因为不管哪个色值,他们的范围都是在0~255之间,这样就可以很轻构的实现。

  • 根据red()green()blue()函数获取任何颜色的R,GB值;
  • 将得到的RGB值与255进行减法运算,分别得到新颜色的R,GB值;
  • 根据不同的颜色函数将颜色转换成自己需要的表达式。(此步可以忽略不计)

实战一下#de90fahsl(30,45%,8%)hsla(232,80%,3%,.6):

>> red(#de90fa)
222
>> green(#de90fa)
144
>> blue(#de90fa)
250
>> red(hsl(30,45%,8%))
30
>> green(hsl(30,45%,8%))
20
>> blue(hsl(30,45%,8%))
11
>> red(hsla(232,80%,3%,.6))
2
>> green(hsla(232,80%,3%,.6))
3
>> blue(hsla(232,80%,3%,.6))
14

将各自颜色组合起来:

#de90fa = rgb(222,144,250)
hsl(30,45%,8%) = rgb(30,20,11);
hsla(232,80%,3%,.6) = rgb(2,3,14);

让各值也255计算得出:

#de90fa 反相 => rgb(33,111,5)
hsl(30,45%,8%)反相 => rgb(225,235,244)
hsla(232,80%,3%,.6)反相 => rgba(253,252,241,.6)//透明度不变

通过rgb()rgba()颜色函数,可以得到新颜色:

>> rgb(33,111,5)
#216f05
>> rgb(225,235,244)
#e1ebf4
>> rgba(253,252,241,.6)
rgba(253, 252, 241, 0.6)

为了验证,我们这样的计算方法是正确的,可以使用invert()函数来验证一下:

//SCSS
$baseColor1: #de90fa;
$baseColor2: hsl(30,45%,8%);
$baseColor3: hsla(232,80%,3%,.6);

.invert1 {
  background: invert($baseColor1);
}
.invert2 {
  background: invert($baseColor2);
}
.invert3 {
  background: invert($baseColor3);
}

//CSS
.invert1 {
  background: #216f05; 
}

.invert2 {
  background: #e1ebf4; 
}

.invert3 {
  background: rgba(253, 252, 241, 0.6); 
}

转译出来的反相颜色与计算出来的反相颜色是一模一样的。

Opacity函数

在CSS中除了可以使用rgbahslatransform来控制颜色透明度之外,还可以使用opacity来控制,只不过前两者只是针对颜色上的透明通道做处理,而后者是控制整个元素的透明度。

在Sass中,也提供了系列透明函数,只不过这系列的透明函数主要用来处理颜色透明度:

alpha()&opacity()函数

alphpa()opacity()函数很简单,与前面介绍的red(),green()等函数很类似。这个函数的主要功能是用来获取一个颜色的透明度值。如果颜色没有特别指定透明度,那么这两个函数得到的值都会是1

>> alpha(red)
1
>> alpha(rgba(red,.8))
0.8
>> opacity(red)
1
>> opacity(rgba(red,.8))
0.8

rgba()函数

在介绍RGB函数一节中,有一个rgba()函数可以创建一个颜色,此这个rgba()函数主要用来对一个颜色修改其透明度。其接受两个参数,第一个参数为颜色,第二个参数是你需要设置的颜色透明值。

>> rgba(red,.5)
rgba(255, 0, 0, 0.5)
>> rgba(#dedede,.5)
rgba(222, 222, 222, 0.5)
>> rgba(rgb(34,45,44),.5)
rgba(34, 45, 44, 0.5)
>> rgba(rgba(33,45,123,.2),.5)
rgba(33, 45, 123, 0.5)
>> rgba(hsl(33,7%,21%),.5)
rgba(57, 54, 50, 0.5)
>> rgba(hsla(33,7%,21%,.9),.5)
rgba(57, 54, 50, 0.5)

opacify() & fade-in()函数

这两个函数是用来对已有颜色的透明度做一个加法运算,会让颜色更加不透明。其接受两个参数,第一个参数是原始颜色,第二个参数是你需要增加的透明度值,其取值范围主要是在0~1之间。当透明度值增加到大于1时,会以1计算,表示颜色不具有任何透明度。

>> opacify(rgba(22,34,235,.6),.2)
rgba(22, 34, 235, 0.8)
>> opacify(rgba(22,34,235,.6),.5)
#1622eb
>> opacify(hsla(22,34%,23%,.6),.15)
rgba(79, 53, 39, 0.75)
>> opacify(hsla(22,34%,23%,.6),.415)
#4f3527
>> opacify(red,.15)
#ff0000
>> opacify(#89adde,.15)
#89adde
>> fade-in(rgba(23,34,34,.5),.15)
rgba(23, 34, 34, 0.65)
>> fade-in(rgba(23,34,34,.5),.615)
#172222

其中fade-in()函数又名fade_in()函数。其所起作用等效。

transparentize() & fade-out()函数

transparentize()fade-out()函数所起作用刚好与opacify()fade-in()函数相反,让颜色更加的透明。这两个函数会让透明值做减法运算,当计算出来的结果小于0时会以0计算,表示全透明。

>> transparentize(red,.5)
rgba(255, 0, 0, 0.5)
>> transparentize(#fde,.9)
rgba(255, 221, 238, 0.1)
>> transparentize(rgba(98,233,124,.3),.11)
rgba(98, 233, 124, 0.19)
>> transparentize(rgba(98,233,124,.3),.51)
rgba(98, 233, 124, 0)
>> fade-out(red,.9)
rgba(255, 0, 0, 0.1)
>> fade-out(hsla(98,6%,23%,.5),.1)
rgba(58, 62, 55, 0.4)
>> fade-out(hsla(98,6%,23%,.5),.6)
rgba(58, 62, 55, 0)

其他颜色函数

除了上述介绍的函数之外,Sass还提供了其他的一些颜色函数:

adjust-color()函数

adjust-color()函数可以同时调整颜色一个或多个属性,获取到一个新的颜色,具体使用语法如下:

adjust-color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])

其中[$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha]这些参数可以同时设置,也可以同时不设置,来看一个官方文档的示例:

>> adjust-color(#102030, $blue: 5)
#102035
>> adjust-color(#102030, $red: -5, $blue: 5)
#0b2035
>> adjust-color(hsl(25, 100%, 80%), $lightness: -30%, $alpha: -0.4)
rgba(255, 106, 0, 0.6)

详细参数描述,请点击这里查阅。

scale-color()函数

scale-color()函数和adjust-color()函数非常相似,同时可以调整颜色多个参数获取新的一个颜色,其使用语法如下:

scale-color($color, [$red], [$green], [$blue], [$saturation], [$lightness], [$alpha])

使用方法如下:

>> scale-color(hsl(120, 70%, 80%), $lightness: 50%)
#d4f7d4
>> scale-color(rgb(200, 150, 170), $green: -40%, $blue: 70%)
#c85ae5
>> scale-color(hsl(200, 70%, 80%), $saturation: -90%, $alpha: -30%)
rgba(200, 205, 208, 0.7)

详细参数描述,请点击这里查阅。

change-color()函数

简单了解一下change-color()函数的使用语法:

change-color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])

看个示例:

>> change-color(#102030, $blue: 5)
#102005
>> change-color(#102030, $red: 120, $blue: 5)
#782005
>> change-color(hsl(25, 100%, 80%), $lightness: 40%, $alpha: 0.8)
rgba(204, 85, 0, 0.8)

详细参数描述,请点击这里查阅。

ie-hex-str()函数

这个函数常配合IE滤镜使用,主要用来转译出适合IE滤镜的颜色代码,如:

>> ie-hex-str(#abc)
"#FFAABBCC"
>> ie-hex-str(#3322BB)
"#FF3322BB"
>> ie-hex-str(rgba(0, 255, 0, 0.5))
"#8000FF00"

有了这个函数之后,不需要在去做任何的人工计算。

函数的嵌套

如果你能一口气看到这里,我想您对Sass的颜色函数已有一个清晰的了解,或者说实战经验。在Sass中除了具有上述颜色函数之外,在实际使用中,还可以将这些函数进行嵌套使用。我们来看一个简单的实例:

//SCSS
$baseColor1: #ad141e;
$baseColor2: #d90fec;

.darken-and-mix {
  background: darken(mix($baseColor1,$baseColor2,20%),20%);
}

//CSS
.darken-and-mix {
  background: #71096a; 
}


Sass基础——颜色函数

这只是一个简单的示例,大家可以尝试进行多重颜色函数的嵌套。

颜色函数实战——七色卡

常见的颜色就是七彩色,红、橙、黄、蓝、绿、紫、黑。那么我们就使用Sass的颜色函数来制作一个这样的色卡。

<ul class="swatches red">
  <li></li>
  ...      
  <li></li>
</ul>
<ul class="swatches orange">
  <li></li>
  …
  <li></li>
</ul>
<ul class="swatches yellow">
   <li></li>
   …
   <li></li>
 </ul>
 <ul class="swatches green">
    <li></li>
      …
    <li></li>
 </ul>
 <ul class="swatches blue">
    <li></li>
    …
    <li></li>
 </ul>
 <ul class="swatches purple">
    <li></li>
    …
    <li></li>
 </ul>
 <ul class="swatches black">
    <li></li>
    …
    <li></li>
  </ul>

结构不做过多的描述。下面我们来看Sass实现色卡代码如何写:

1、定义七色变量

首要的就是变量,此处设置了一个红色系的变量值,然后其他色系的变量值,都是通过嵌套颜色函数完成:

//定义变量
$redBase: #DC143C;
$orangeBase: saturate(lighten(adjust_hue($redBase, 39), 5), 7);//#f37a16
$yellowBase: saturate(lighten(adjust_hue($redBase, 64), 6), 13);//#fbdc14
$greenBase: desaturate(darken(adjust_hue($redBase, 102), 2), 11);//#73c620
$blueBase: saturate(darken(adjust_hue($redBase, 201), 2), 1);//#12b7d4
$purpleBase: saturate(darken(adjust_hue($redBase, 296), 2), 1);//#a012d4
$blackBase: #777;
$bgc: #fff;

从上在的变量中可以看出,黄、橙、绿、蓝、紫这几个色系都和红色色系有关,因为这几个都是在红色基础上通过多个嵌套函数而生面的色系变量。这样做的好处是,修改一个变量,就能实现另外一套色卡。

2、定义mixin

色卡是有很多种颜色的,我们需要在一个颜色的基础上,让颜色在亮度上做一个调整(当然也可以是在饱和度上),因此我们需要定义两个mixins

//定义颜色变暗的mixin
@mixin swatchesDarken($color) {
    @for $i from 1 through 10 {
        $x:$i+11;
        li:nth-child(#{$x}) {
            $n:$i*5;
            $bgc:darken($color,$n); //颜色变暗
            background-color: $bgc;
            &:hover:before { //hover状态显示颜色编号
                content: "#{$bgc}";
                color: lighten($bgc,40);
                font-family: verdana;
                font-size: 8px;
                padding: 2px;
            }
        }
    }
}
//定义颜色变亮的mixin
@mixin swatchesLighten($color) {
    @for $i from 1 through 10 {
        $x:11-$i;
        li:nth-child(#{$x}) {
            $n:$i*5;
            $bgc:lighten($color,$n);
            background-color: $bgc;
            &:hover:before {
                content: "#{$bgc}";
                color: darken($bgc,40);
                font-family: verdana;
                font-size: 8px;
                padding: 2px;
            }
        }
    }
}

3、调用mixin

完成上面的工作,只需要根据所需进行调用,生成色卡:

.swatches li {    
    width: 4.7619047619%;
    float: left;
    height: 60px;
    list-style: none outside none;
}


ul.red { 
    @include swatchesLighten($redBase);
    @include swatchesDarken($redBase);
    li:nth-child(11) {
        background-color: $redBase;
    }
}

ul.orange { 
    @include swatchesLighten($orangeBase);
    @include swatchesDarken($orangeBase);
    li:nth-child(11) {
        background-color: $orangeBase;
    }
}


ul.yellow { 
    @include swatchesLighten($yellowBase);
    @include swatchesDarken($yellowBase);
    li:nth-child(11) {
        background-color: $yellowBase;
    }
}

ul.green { 
    @include swatchesLighten($greenBase);
    @include swatchesDarken($greenBase);
    li:nth-child(11) {
        background-color: $greenBase;
    }
}

ul.blue { 
    @include swatchesLighten($blueBase);
    @include swatchesDarken($blueBase);
    li:nth-child(11) {
        background-color: $blueBase;
    }
}

ul.purple { 
    @include swatchesLighten($purpleBase);
    @include swatchesDarken($purpleBase);
    li:nth-child(11) {
        background-color: $purpleBase;
    }
}

ul.black { 
    @include swatchesLighten($blackBase);
    @include swatchesDarken($blackBase);
    li:nth-child(11) {
        background-color: $blackBase;
    }
}

这样就完成了色卡的制作,我们来看看效果:


Sass基础——颜色函数

这个时候只需将变量稍做调整,颜色就有变化:

$redBase: #f00d3b;


Sass基础——颜色函数

总结

在这章节中主要介绍了Sass中的颜色函数。按大类分,其主要包括RGB函数、HSL函数、Opacity函数以及一些其他的函数。在各个部分中都有一些常用的函数,这些函数功能能帮助我们更好的控制Web中的颜色,比如说渐变、边框,文本等,让你的UI在细彩上体现的更佳细腻,美观。给人具有专业水准的感觉。

在众多颜色函数当中,每个颜色函数都有其自己的功能与作用,以及所处的位置。但从侧重面来说,RGB函数系列中的rgba()函数、mix()函数;HSL函数系列中的lighten()darken()saturate()desaturate()Opacity函数系列中的rgba()以及ie-hex-str()函数在平时的使用中频率较高。但我个人建议您要是对此感兴趣,不仿每个函数的使用都过一遍。最后希望这篇文章对于初学Sass的同学有所帮助。
<div

Sass函数功能——rem转px

express阅读(35)

<

div class=”entry-content clearfix”>

本文由大漠根据David Walsh的《REM to PX Browser Function with Sass》所译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://davidwalsh.name/rem-px-browser-function-sass,以及作者相关信息

性能对于Web前端开发人员是必备的一项技能。CSS3和HTML5的新特性帮助我们改善了应用程序,但有时这些特性并没有得到很好的支持。这就是优雅降级。你想在新的浏览器中使用这些特性,但不能忽视对传统浏览器的支持。我最近开始在做一个新的项目,他必须要支持IE8。由于级联问题的嵌套,使用EM单位时不好把控,所以我决定在这个项目中开始使用有用的rem单位,这样更容易理解和维护。这种方法的主要问题是IE8不支持rem单位。最后,我们需要针对于这种情景创建一个后备方案:使用px单位做降级处理。

性能和编码速度

你会发现,在网络上关于rem px mixin有很多有用的话题和讨论,本文以这些文章做了一定的参考研究。大部分他们都是依赖于相同的技术,使用Sass mixin产生两次CSS属性,如:

SCSS

.header {
 @include rempx(margin, 1rem 2rem);
}

编译出来的CSS:

CSS

.header {
 margin:16px 32px; /* Fallback */
 margin:1rem 2rem;
}

主要的问题是每使用这个mixin什么重复写CSS样式,这样整个CSS样式体重就会增长。这种技术有两个属性,而不是一个。第一个是用在不支持Rem单位的浏览器上。代码不怎么干净,但它是灵活的和易于维护。因为我们知道rem单位在IE8中不被支持,但是,我们要是有两不同的样式表呢?

第二个问题是,使用上面的方法存在输入速度问题。每次你想添加一个新的CSS属性都得输入一次@include rempx(property,values),这不是最优秀的方法。

提供不同的样式表

我们的第一个目标是有两个分开的样式表:

  • main.css文件用于标准浏览器,使用rem单位
  • main-ie.css文件用于IE8浏览器,使用px单位

这两个文件将会有完全相同的CSS内容,只是单位不同。

Nicolas Gallagher向我们展示了如何在标准浏览器和IE浏览器中加载不同的CSS文件,如下所示:

<!--[if (gt IE 8) | (IEMobile)]><!-->
  <link rel="stylesheet" href="/css/main.css">
<!--<![endif]-->

<!--[if (lt IE 9) & (!IEMobile)]>
  <link rel="stylesheet" href="/css/main-ie.css">
<![endif]-->

标准浏览器将下载main.css文件,而IE浏览器下将下载main-ie.css文件。这将确保客户端没有下载这两个CSS文件。

我们的第二个目标是使用@mixin技术,所以我们只需要维护一个文件。

Sass解决文案

现在我们知道如何调用不同的样式表,我们现在需要生成两个CSS文件。这个时候我们需要把Sass引进来。为了使用这个示例尽量的简单,我不会给Sass使用一个特殊的文件结构,只是一群.scss文件。这是我们示例中使用的结构:

  • 一个空的css文件夹
  • 一个sass文件夹,里面有四个文件:main.scssmain-ie.scss_function.scss_module-example.scss

main.scss

// 配置
$px-only:false;

// 导入Sass的函数文件
@import "functions";

// 导入网站的模块文件
@import "module-example.scss";

main-ie.scss

// 配置
$px-only:true;

// 导入Sass的函数文件
@import "functions";

// 导入网站模块文件
@import "module-example.scss";

_function.scss

$pixelBase : 16; /* 1 */

@function parseInt($n) {
    @return $n / ($n * 0 + 1); /* 2 */
}

@function u($values){ /* 3 */

      $list: (); /* 4 */

      @each $value in $values { /* 5 */

            $unit : unit($value); /* 6 */
            $val  : parseInt($value); /* 2 */

            @if ($px-only) and ($unit == 'rem') { /* 7 */
                  $list: append($list, ($val * $pixelBase) + px); /* 7 */
            }

            @else if($unit == 'px') or ($unit == 'rem'){ /* 8 */
                  $list: append($list, $value); /* 8 */
            }

            @else {
                  @warn 'There is no unit conversion for #{$unit}'; /* 9 */
            }

      }

      @return $list(); /* 10 */

}

它是如何工作的?

变量$px-only不仅仅是属于main.scssmain-ie.scss文件内。所有导入的文件都将影响$px-only的值。当u()函数加载时,main.scss或者main-ie.scss都指定了变量$px-only的值。为了其他模块能正常工作,必须先导入这个Sass函数。

函数的解释

  1. 这个变量是指默认浏览器的字体大小和1rem = 16px。为了更好的维护,我们将此值存储在一个变量中,以便重用和容易修改。
  2. 这个函数返回一个数字的这符串,此函数由Hugo提供
  3. 我们称为函数u,因为它更容易输入。u也代表单位。这个函数接受一个参数,一个rem或者px值的数组。
  4. 我们定义一个新的列表,将保存新值。
  5. $valuse参数里的每个$value值,通过测试当前的$value值并将其存储在$list数组内。
  6. 这个Sass函数返回一个带单位的数字。在我们的例子中,是px或者rem
  7. 首要条件:如果当前模式是像素模式和单位的值为rem,那么rem值将转换为px并把它们放到$list数组中。
  8. 第二个条件:如果单位是px或rem,我们只是将值入到列表中。
  9. 如果第一个和第二个条件失败,我们在Sass控制台上输入一个警告信息。
  10. 最后,我们返回整个简洁的CSS值列表。

使用

_module-example.scss

.main-header {
 margin:u(1rem 2rem 20px 3rem);
 padding-bottom:u(0.25rem);
 font-size:u(0.875rem);
}

转译出来的CSS

main.css

.main-header {
 margin: 1rem 2rem 20px 3rem;
 padding-bottom: 0.25rem;
 font-size: 0.875rem;
}

main-ie.csss

.main-header {
 margin: 16px 32px 20px 48px;
 padding-bottom: 4px;
 font-size: 14px;
}

优点和缺点

优点

  • 易于维护:一旦编辑代码,将生成两个不同的样式表
  • 容易阅读:你最后的CSS是干净的,没有未使用的属性
  • 降低文件大小:你最好的CSS是轻量级的
  • 快速开发:快速输入u()来生成最终需要的单位

缺点

  • 需要在<head>内使用条件样式引入正确的样式表

我希望得到您的反馈和分享你的任何想法,哪些地方可以改进!

扩展阅读

<div

Sass制作Font Awesome图标

express阅读(34)

<

div class=”entry-content clearfix”>
Font AwesomeDave Gandy通过字体制作的几百个icons图标。在前端界享有盛名。使用@font-face制作的图标可以随意的放大,并通过CSS中字体相关的CSS对图标进行美化,比如说可以改变图标颜色、大小和增加阴影等,但他也存在一定的弊端。

很多时候,在项目中为了调用整套图标中的某几个时,为了使用Font Awesome制作的图标,我们不得不被迫加载制作icon的所有样式和文件。比如:

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

如此一来,造成文件臃肿,而且有很多冗余没用的代码。

这个时候,我们都在思考,有没有办法能帮助我们,使用Font Awesome图标能按我们所需调用需要图标的样式。换句话说,如果我们需要一个图标,就使用这个图标对应的样式,如果我们需要某几个图标,我们就使用这几个图标对应的样式。看似蛮有意思,那么我们今天,就一起来探讨这个问题。

Sass功能

带着这样的问题,我在想,是否可以使用CSS预处理器语言中的Sass来进行处理。了解Sass的同学都知道,Sass可以进行一些预编码处理,比如说定义mixins、%placeholder等,当需要使用的时候,通过@include和@extend来调用。甚至还可以像其他程序一样,定义函数功能,实现一些自定的功能。那么我们今天就借助Sass的这些特性,来做进一步的思考,是否能通过Sass来帮助我们实现我们前面所说的需求。

实现思路

在Font Awesome字体图库中,每个图标都有一个对应的编码,比如说glass=>"f000",music=>"f001"。整个图库我们有近三百个不同的图标,也就是说我们有三百多个这样的实体编码。那么针对这种现像,我们是否可以考虑像其他的程序语言一样,给他们定义一个数组,并将此数组赋值给一个变量。按照这样的思路来说,在Sass中正好具有这样的特性,我们可以将所有图标对应的编码以数组的形式赋值给一个变量。

有了数组就解决我们一大问题,为什么这么说呢?打个比方,我们需要其中的某个图标,我们是否需要一个类似遍历数组的函数,从整个列表中找到需要的东西。也就是说,我们需要在Sass中定义一个遍历数组的函数。

有了变量,也有了遍历功能,能帮助我们找到需要的图标,但我们还需要一些默认的样式功能,比如说,图标怎么调用,这个时候我们就需要通过Sass的mixin来制作,便于每次的调用。

数组、函数和功能都具有了,这个时候我们回到CSS面对的问题中。前面说过,在CSS中使用Font Awesome图库,不管我们需要使用的图标有多少,我们都必须全部加载。而我们真正需要的是要有一个开关——按需开启。也就是说,如果我只需要某几个图标,我能通过一定的方式只开启这几个对应的图标,调出他们对应的样式。如果我们需要所有的图标显示,我也有一个功能开关,可以通过某个功能,一下全部开启。

如此一来,我们的思路就很清楚了,我们使用Sass制作灵活开启图标,需要以下几个东东:

  • 数组:用来定义所有的图标对应的实体编码
  • 引用字体的Mixin:通过mixin,调用@font-face所需的字体
  • 调用单个图标的Mixin:通过这个mixin按需实现单个或某几个图标
  • 调用合部图标的Mixin:通过这个mixin,实现是否开启有所图标
  • 遍历数组的函数:通过这个遍历函数,获取所需要的图标变量

扯了一大通,大家可能想知道的是如何用Sass实现前面说的这一切。那我们现在就开始。

项目结构

为了更好的说明整个实现过程,我们先创建本地创建一个项目,并把制作Font Awesome图标所需要的字体文件引入到项目中。而其中我们同时制作了一个文件夹”sass”来放置.scss文件,并且创建一个文件夹”css”,用来放置Sass编译出来的.css文件。整个项目的结构如下所示:

+font-awesome
|-+--fonts
|-|----fontawesome-webfont.eot
|-|----fontawesome-webfont.svg
|-|----fontawesome-webfont.ttf
|-|----fontawesome-webfont.woff
|-+--stylesheets
|-|--+--sass
|-|--+--css

声明数组

在Font Awesome的CSS样式当中,我们能看到一大堆类似于下面的代码:

...
.fa-film:before {
 content: "f008";
}
.fa-th-large:before {
 content: "f009";
}
...

而当中每个"f008"这样的编码就是对应的一个图标,而在Sass中,我们也需要这样的编码,不过不同的是,我们将其以数组的方式定义的。为了能更好的组织这些编码和其他相应的变量,特些在sass目录中创建了一个名叫_variables.scss的文件,并且在这个文件中放置如下所示的代码:

@charset "UTF-8";

//Variables

$fa-css-prefix:                 icon- !default;
$fa-family-name:                "FontAwesome" !default;
$file-path:                     "../../fonts/fontawesome-webfont" !default;

$icons:
    glass                       "f000",
    music                       "f001",
    search                      "f002",
    envelope-o                  "f003",
    heart                       "f004",
    star                        "f005",
    star-o                      "f006",
    user                        "f007",
    film                        "f008",
    th-large                    "f009",
    th                          "f00a",
    th-list                     "f00b",
    check                       "f00c",
    times                       "f00d",
    search-plus                 "f00e",
    search-minus                "f010",
    power-off                   "f011",
    signal                      "f012",
    cog                         "f013",
    trash-o                     "f014",
    home                        "f015",
    file-o                      "f016",
    clock-o                     "f017",
    road                        "f018",
    download                    "f019",
    arrow-circle-o-down         "f01a",
    arrow-circle-o-up           "f01b",
    inbox                       "f01c",
    play-circle-o               "f01d",
    repeat                      "f01e",
    refresh                     "f021",
    list-alt                    "f022",
    lock                        "f023",
    flag                        "f024",
    headphones                  "f025",
    volume-off                  "f026",
    volume-down                 "f027",
    volume-up                   "f028",
    qrcode                      "f029",
    barcode                     "f02a",
    tag                         "f02b",
    tags                        "f02c",
    book                        "f02d",
    bookmark                    "f02e",
    print                       "f02f",
    camera                      "f030",
    font                        "f031",
    bold                        "f032",
    italic                      "f033",
    text-height                 "f034",
    text-width                  "f035",
    align-left                  "f036",
    align-center                "f037",
    align-right                 "f038",
    align-justify               "f039",
    list                        "f03a",
    outdent                     "f03b",
    indent                      "f03c",
    video-camera                "f03d",
    picture-o                   "f03e",
    pencil                      "f040",
    map-marker                  "f041",
    adjust                      "f042",
    tint                        "f043",
    pencil-square-o             "f044",
    share-square-o              "f045",
    check-square-o              "f046",
    arrows                      "f047",
    step-backward               "f048",
    fast-backward               "f049",
    backward                    "f04a",
    play                        "f04b",
    pause                       "f04c",
    stop                        "f04d",
    forward                     "f04e",
    fast-forward                "f050",
    step-forward                "f051",
    eject                       "f052",
    chevron-left                "f053",
    chevron-right               "f054",
    plus-circle                 "f055",
    minus-circle                "f056",
    times-circle                "f057",
    check-circle                "f058",
    question-circle             "f059",
    info-circle                 "f05a",
    crosshairs                  "f05b",
    times-circle-o              "f05c",
    check-circle-o              "f05d",
    ban                         "f05e",
    arrow-left                  "f060",
    arrow-right                 "f061",
    arrow-up                    "f062",
    arrow-down                  "f063",
    share                       "f064",
    expand                      "f065",
    compress                    "f066",
    plus                        "f067",
    minus                       "f068",
    asterisk                    "f069",
    exclamation-circle          "f06a",
    gift                        "f06b",
    leaf                        "f06c",
    fire                        "f06d",
    eye                         "f06e",
    eye-slash                   "f070",
    exclamation-triangle        "f071",
    plane                       "f072",
    calendar                    "f073",
    random                      "f074",
    comment                     "f075",
    magnet                      "f076",
    chevron-up                  "f077",
    chevron-down                "f078",
    retweet                     "f079",
    shopping-cart               "f07a",
    folder                      "f07b",
    folder-open                 "f07c",
    arrows-v                    "f07d",
    arrows-h                    "f07e",
    bar-chart-o                 "f080",
    twitter-square              "f081",
    facebook-square             "f082",
    camera-retro                "f083",
    key                         "f084",
    cogs                        "f085",
    comments                    "f086",
    thumbs-o-up                 "f087",
    thumbs-o-down               "f088",
    star-half                   "f089",
    heart-o                     "f08a",
    sign-out                    "f08b",
    linkedin-square             "f08c",
    thumb-tack                  "f08d",
    external-link               "f08e",
    sign-in                     "f090",
    trophy                      "f091",
    github-square               "f092",
    upload                      "f093",
    lemon-o                     "f094",
    phone                       "f095",
    square-o                    "f096",
    bookmark-o                  "f097",
    phone-square                "f098",
    twitter                     "f099",
    facebook                    "f09a",
    github                      "f09b",
    unlock                      "f09c",
    credit-card                 "f09d",
    rss                         "f09e",
    hdd-o                       "f0a0",
    bullhorn                    "f0a1",
    bell                        "f0f3",
    certificate                 "f0a3",
    hand-o-right                "f0a4",
    hand-o-left                 "f0a5",
    hand-o-up                   "f0a6",
    hand-o-down                 "f0a7",
    arrow-circle-left           "f0a8",
    arrow-circle-right          "f0a9",
    arrow-circle-up             "f0aa",
    arrow-circle-down           "f0ab",
    globe                       "f0ac",
    wrench                      "f0ad",
    tasks                       "f0ae",
    filter                      "f0b0",
    briefcase                   "f0b1",
    arrows-alt                  "f0b2",
    users                       "f0c0",
    link                        "f0c1",
    cloud                       "f0c2",
    flask                       "f0c3",
    scissors                    "f0c4",
    files-o                     "f0c5",
    paperclip                   "f0c6",
    floppy-o                    "f0c7",
    square                      "f0c8",
    bars                        "f0c9",
    list-ul                     "f0ca",
    list-ol                     "f0cb",
    strikethrough               "f0cc",
    underline                   "f0cd",
    table                       "f0ce",
    magic                       "f0d0",
    truck                       "f0d1",
    pinterest                   "f0d2",
    pinterest-square            "f0d3",
    google-plus-square          "f0d4",
    google-plus                 "f0d5",
    money                       "f0d6",
    caret-down                  "f0d7",
    caret-up                    "f0d8",
    caret-left                  "f0d9",
    caret-right                 "f0da",
    columns                     "f0db",
    sort                        "f0dc",
    sort-down                   "f0dc",
    sort-asc                    "f0dd",
    sort-desc                   "f0de",
    envelope                    "f0e0",
    linkedin                    "f0e1",
    undo                        "f0e2",
    gavel                       "f0e3",
    tachometer                  "f0e4",
    dashboard                   "f0e4",
    comment-o                   "f0e5",
    comments-o                  "f0e6",
    bolt                        "f0e7",
    sitemap                     "f0e8",
    umbrella                    "f0e9",
    clipboard                   "f0ea",
    lightbulb-o                 "f0eb",
    exchange                    "f0ec",
    cloud-download              "f0ed",
    cloud-upload                "f0ee",
    user-md                     "f0f0",
    stethoscope                 "f0f1",
    suitcase                    "f0f2",
    bell-o                      "f0a2",
    coffee                      "f0f4",
    cutlery                     "f0f5",
    file-text-o                 "f0f6",
    building-o                  "f0f7",
    hospital-o                  "f0f8",
    ambulance                   "f0f9",
    medkit                      "f0fa",
    fighter-jet                 "f0fb",
    beer                        "f0fc",
    h-square                    "f0fd",
    plus-square                 "f0fe",
    angle-double-left           "f100",
    angle-double-right          "f101",
    angle-double-up             "f102",
    angle-double-down           "f103",
    angle-left                  "f104",
    angle-right                 "f105",
    angle-up                    "f106",
    angle-down                  "f107",
    desktop                     "f108",
    laptop                      "f109",
    tablet                      "f10a",
    mobile                      "f10b",
    mobile-phone                "f10b",
    circle-o                    "f10c",
    quote-left                  "f10d",
    quote-right                 "f10e",
    spinner                     "f110",
    circle                      "f111",
    reply                       "f112",
    github-alt                  "f113",
    folder-o                    "f114",
    folder-open-o               "f115",
    smile-o                     "f118",
    frown-o                     "f119",
    meh-o                       "f11a",
    gamepad                     "f11b",
    keyboard-o                  "f11c",
    flag-o                      "f11d",
    flag-checkered              "f11e",
    terminal                    "f120",
    code                        "f121",
    reply-all                   "f122",
    mail-reply-all              "f122",
    star-half-o                 "f123",
    location-arrow              "f124",
    crop                        "f125",
    code-fork                   "f126",
    chain-broken                "f127",
    question                    "f128",
    info                        "f129",
    exclamation                 "f12a",
    superscript                 "f12b",
    subscript                   "f12c",
    eraser                      "f12d",
    puzzle-piece                "f12e",
    microphone                  "f130",
    microphone-slash            "f131",
    shield                      "f132",
    calendar-o                  "f133",
    fire-extinguisher           "f134",
    rocket                      "f135",
    maxcdn                      "f136",
    chevron-circle-left         "f137",
    chevron-circle-right        "f138",
    chevron-circle-up           "f139",
    chevron-circle-down         "f13a",
    html5                       "f13b",
    css3                        "f13c",
    anchor                      "f13d",
    unlock-alt                  "f13e",
    bullseye                    "f140",
    ellipsis-h                  "f141",
    ellipsis-v                  "f142",
    rss-square                  "f143",
    play-circle                 "f144",
    ticket                      "f145",
    minus-square                "f146",
    minus-square-o              "f147",
    level-up                    "f148",
    level-down                  "f149",
    check-square                "f14a",
    pencil-square               "f14b",
    external-link-square        "f14c",
    share-square                "f14d",
    compass                     "f14e",
    caret-square-o-down         "f150",
    caret-square-o-up           "f151",
    caret-square-o-right        "f152",
    eur                         "f153",
    gbp                         "f154",
    usd                         "f155",
    inr                         "f156",
    jpy                         "f157",
    rub                         "f158",
    ruble                       "f158",
    rouble                      "f158",
    krw                         "f159",
    btc                         "f15a",
    file                        "f15b",
    file-text                   "f15c",
    sort-alpha-asc              "f15d",
    sort-alpha-desc             "f15e",
    sort-amount-asc             "f160",
    sort-amount-desc            "f161",
    sort-numeric-asc            "f162",
    sort-numeric-desc           "f163",
    thumbs-up                   "f164",
    thumbs-down                 "f165",
    youtube-square              "f166",
    youtube                     "f167",
    xing                        "f168",
    xing-square                 "f169",
    youtube-play                "f16a",
    dropbox                     "f16b",
    stack-overflow              "f16c",
    instagram                   "f16d",
    flickr                      "f16e",
    adn                         "f170",
    bitbucket                   "f171",
    bitbucket-square            "f172",
    tumblr                      "f173",
    tumblr-square               "f174",
    long-arrow-down             "f175",
    long-arrow-up               "f176",
    long-arrow-left             "f177",
    long-arrow-right            "f178",
    apple                       "f179",
    windows                     "f17a",
    android                     "f17b",
    linux                       "f17c",
    dribbble                    "f17d",
    skype                       "f17e",
    foursquare                  "f180",
    trello                      "f181",
    female                      "f182",
    male                        "f183",
    gittip                      "f184",
    sun-o                       "f185",
    moon-o                      "f186",
    archive                     "f187",
    bug                         "f188",
    vk                          "f189",
    weibo                       "f18a",
    renren                      "f18b",
    pagelines                   "f18c",
    stack-exchange              "f18d",
    arrow-circle-o-right        "f18e",
    arrow-circle-o-left         "f190",
    caret-square-o-left         "f191",
    toggle-left                 "f191",
    dot-circle-o                "f192",
    wheelchair                  "f193",
    vimeo-square                "f194",
    try                         "f195",
    plus-square-o               "f196";

在这里,每一个图标我们都是用icon-定义类名,比如说icon-glass。那么了为节约时间,在变量中我们特意定义了一个默认变量:

$fa-css-prefix: icon- !default;

另外为了调用字体和字体文件方便,因此还定义了另外两个变量:

$fa-family-name: "FontAwesome" !default;
$file-path: "../../fonts/fontawesome-webfont" !default;

这样字体font-family定义了名称为“FontAwesome”,而且指定了一个变量$file-path来引用字体文件路径。特别需要注意的是,需要根据项目指定不同的路径。如果您要是使用compass的话,可以通过config.rb文件来指定这个路径。不过这里对此不做过多的描述。

变量$icons是我们最需要的,像其他程序一样,通过以key=>value方式定义了所有图标需要的实体编码。并以数组方式赋值给变量$icons

定义font-face Mixin

要使用字体图标,就离不开@font-face。使用@font-face主要是引用字体,调用特定的字体,这也是最基础的。在此,我们通过定义一个mixin,在需要的就时候使用。

@mixin font-face($font-family,$file-path,$font-weight: normal,$font-style: normal,$asset-pipeline:false){
    @font-face {
        font: {
            family: $font-family;
            weight: $font-weight;
            style: $font-style;
        }

        @if $asset-pipeline == true {
            src: font-url("#{$file-path}.eot");
            src: font-url("#{$file-path}.eot?#iefix") format("embedded-opentype"),
                 font-url("#{$file-path}.woff") format("woff"),
                 font-url("#{$file-path}.ttf") format("truetype"),
                 font-url("#{$file-path}.svg##{$font-family}") format("svg");
        }
        @else {
            src: url("#{$file-path}.eot");
            src: url("#{$file-path}.eot?#iefix") format("embedded-opentype"),
                 url("#{$file-path}.woff") format("woff"),
                 url("#{$file-path}.ttf") format("truetype"),
                 url("#{$file-path}.svg##{$font-family}") format("svg");    
        }
    }
}

font-face的mixin中,我们传了几个参数给他:

  • $font-family:用来定义自定义的字体名称,在这个示例中指的是“FontAwesome”;
  • $file-path:用来定义引用web字体的路径;
  • $font-weight:用来设置字体的粗细,这里给他传了一个默认参数normal
  • $font-style:用来设置字体的样式,这里给他也传了一个默认参数normal
  • $asset-pipeline:这个主要是用于ruby环境之下,用来定义字体的在Rails下的路径。也就是说asset-pipeline用来替代app/assets/fonts下的fonts。这里也传递了一个参数true

定义好font-face的mixin时,在需要使用@font-face时,只需要通过@include来调用:

@include font-face($fa-family-name,$file-path,normal,normal,$asset-pipeline:false);

在调用的时候也指定了mixin的参数:

  • $fa-family-name:指的是在_variables.scss中定义的变量,其值为“FontAwesome”;
  • $file-path:指的是在_variables.scss中定义的变量,其值为../../fonts/fontawesome-webfont,具体路径需要根据自身项目字体文件的相对路径来进行设置;
  • normal:指的是参数中的font-weightfont-style,并且值都为normal;
  • $asset-pipeline:传了参数为false,表示不使用Rails下指定的字体。其在font-face当中会调用下面对应的代码:
src: url("#{$file-path}.eot");
src: url("#{$file-path}.eot?#iefix") format("embedded-opentype"),
     url("#{$file-path}.woff") format("woff"),
     url("#{$file-path}.ttf") format("truetype"),
     url("#{$file-path}.svg##{$font-family}") format("svg");

上面代码编译出来的CSS:

@font-face {
 font-family: "FontAwesome";
 font-weight: normal;
 font-style: normal;
 src: url("../../fonts/fontawesome-webfont.eot");
 src: url("../../fonts/fontawesome-webfont.eot?#iefix") format("embedded-opentype"), 
 url("../../fonts/fontawesome-webfont.woff") format("woff"), 
 url("../../fonts/fontawesome-webfont.ttf") format("truetype"), 
 url("../../fonts/fontawesome-webfont.svg#FontAwesome") format("svg"); 
}

定义icon Mixin

在Font Awesome中,样式都是通过元素的伪类:before来制作icon样式,如下所示:

 display: inline-block;
 font-family: "FontAwesome";
 font-style: normal;
 font-weight: normal;
 line-height: 1;
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale; }

同时为每个不同的icon调用不同的实体编码:

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

接下来,我们就需要定义一个mixin来实现上述代码等同功能。在这个示例中,定义了icon的mixin。

 

@mixin icon($position: "before",$styles:true,$icon:false) {
    &:#{$position} {

        @if $icon {
            content: match($icons, $icon);
        }
        @if $styles {
            display: inline-block;
            font: {
                family: $fa-family-name;
                style: normal;
                weight: normal;
            }   
            line-height: 1;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
        }
        @content;
    }
}

在整个icon的mixin中,也设置了三个参数:

  • $position:用来定义伪类,放置icon图标。也就是图标在元素的前面还是后面。这里传了一个默认参数:before。如果你需要放置在元素后面的时候,调用时,可以使用:after。稍后我们可以演示一下。
  • $styles:用来做为是否调用默认样式的参数,这里传默认参数为true,将会调用@if $styles{}中带有的样式;
  • $icon:用来指定icon对应的实体编码。这里传参数为false,如果参数为指定的值时,会自动通过match()函数给对应的图标匹配一个实体编码,并赋值给content

在整个mixin中,还调用了@content,其主要功能就是。如果你想给某个图标设置不同样式时,可以通过他来引用其他样式。

定义好这个mixin,我们就可以通过@include icon和附有具体参数来实现需要的效果:

引用icon需要的样式

[class^="#{$fa-css-prefix}"],
[class*="#{$fa-css-prefix}"] {
 @include icon;
}

上面指的icon定义在:before上,并且指定默认样式,但不引用具体的实体编码,编译出来的CSS如下:

 display: inline-block;
 font-family: "FontAwesome";
 font-style: normal;
 font-weight: normal;
 line-height: 1;
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale; }

指定实体编码

每个图标都需要对应的实体编码,字体图标才会起效果,比如说icon-glass对应的是"f000",这个时候可以按下面的方式调用:

.#{$fa-css-prefix}glass{
 @include icon("before",false,"glass");
}

编译出来的CSS:

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

很多时候,你可能想让图标放在后面,那么我们可稍做修改来实现:

.#{$fa-css-prefix}music{
 @include icon("after",false,"music");
}

编译出来的CSS:

.icon-music:after {
 content: "f001"; }

也有的时候,你的图标没有像前面所示的有一个公用的样式(当然这种情况不会存在),这里为了演示说明icon的功能,我们来做一个示例:

.#{$fa-css-prefix}glass{
 @include icon("before",true,"glass");
}

编译出来的CSS:

.icon-glass:before {
 content: "f000";
 display: inline-block;
 font-family: "FontAwesome";
 font-style: normal;
 font-weight: normal;
 line-height: 1;
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale; }

当然,你为了给某个图标有不同的样式,比如说图标更大,或者带有阴影之类,可以通过icon的mixin中的@content功能来实现:

.#{$fa-css-prefix}glass{
 @include icon("before",false,"glass"){
 font-size: 2rem;
 color: green;
 text-shadow: 1px 1px rgba(0,0,0,.5);
 };
}

编译出来的CSS:

.icon-glass:before {
 content: "f000";
 font-size: 2rem;
 color: green;
 text-shadow: 1px 1px rgba(0, 0, 0, 0.5); }

这也就实现也文章开头所说的,按需开启需要的icons,不会让你的样式文件调用不需要的图标样式。好处就不多说了,上面演示的示例更说明了一切。

macth函数

实现按需开启icon功能,其中macth函数功不可没。因为在Sass中没有类似于map功能的函数。这样一来,就无法像其他程序语言一样,通过key找到其对应的value值。这样一来,按需开启图标一切都是浮云。

不过还好,Hugo大师在Sass中创建了一个match函数,用来模拟map的功能:

@function match($haystack,$needle){
 @each $item in $haystack {
 $index: index($item, $needle);
 @if $index {
 $return: if($index == 1, 2, $index);
 @return nth($item, $return);
 }
 }
 @return false;
}

详细介绍,请点击Mapping with nested lists

定义get-icons mixin

话又说回来,有时候你的可能需要使用很多很多的icons图标,几乎是将里面的图标都用到了,你可能会说,前面的按需开启的方式又会让你觉得不方便,很痛苦。其实不用担心,我们可以定义另一个mixin,并给这个mixin定认一个开关,需要的时候我就开启他,不需要的时候我就不开启他。

在这个get-icons中有两个最为关键,第一给这个mixin定义了一个参数$All-icons,并且默认传参数false,表示默认不开启。另外也个最重要的是通过Sass的@each函数来做循环处理。这个@each主要是针对于数组变量$icons的变量值进行遍历循环。具体代码如下所示:

@mixin get-icons($All-icons:false) {
 @if $All-icons {
 @each $icon in $icons {
 $name: nth($icon, 1);
 .#{$fa-css-prefix}#{$name}{
 @include icon("before",false,$name);
 }
 }
 }
}

有了这个get-icons的mixin,如果你想开启变量$icons指定的所有图标的时候,你只需要按下面的方式来引用:

@include get-icons(true);

编译出来的CSS:

.icon-glass:before {
 content: "f000"; }
.
.
.
.icon-plus-square-o:before {
 content: "f196"; }

如何使用

有了这个模块,就算你不使用Font Awesome字体图标,你也可以快速的完成。你唯一需要修改的就是变量文件_variables.scss对应的几个变量:

  • $fa-family-name: 字体名称
  • $file-path:字体路径
  • $icons:字体编码数组,这个非常重要。

修改完成后,其他调用方式如上面所示。当然你的结构中需要有类似下面这样的结构,并且命名要和$icons中的key值对应起来。

<a href="../icon/rub"><i class="icon icon-rub"></i> icon-rub</a>

当然,如果你不想以icon-前缀开头时,也你可以换成别的。别如Font Awesome中就换成了:

<a href="../icon/rub"><i class="fa fa-rub"></i> icon-rub</a>

这个时候你只需要将$fa-css-prefix变量设置为fa-就行了。有了这一切是不是让你觉得很方便、很简单了。

总结

本文主要通过Sass实现预编码的特性,实现按需开启需要的图标。并在此以著名的字体图标Font Awesome为例。整个功能的实现主要依赖于创建字体编码数值、定义font-faceiconget-icons三个mixin和一个match函数来实现。

如果你有足够多的耐性跟到此处,我想你对这几个功能也有所了解。不过实战是验证真理的最好方式。不仿自己动手一试吧。我想你会有所收获的。如果您有更好的解决方案或者对上面的mixin和function有更好的优化,请在下面的评论中与我们一起分享。

扩展阅读

查看源代码      下载代码

<div

为什么要使用Sass

express阅读(37)

<

div class=”entry-content clearfix”>

本文由若强根据DAN CEDERHOLM的《Why Sass?》所译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://alistapart.com/article/why-sass,以及作者相关信息

小提示:我们很高兴为你提供一个摘录,它是由Dan Cederholm 写的一本叫做Sass For Web Designers的书。你可以快速在一个叫A Book Apart的书城找到它们。

我Sass对略微有点抵触,我更喜欢直接写css样式!我不需要使用它!此外,我确实不想给我的工作流程中增加额外的复杂的部分,因此我选择远离它。

这就我们的常规想法,但是Sass(以及其他css预处理程序)确实是一个强大的工具,它可以让任何形式的样式都能够方便的引入开发工作中去。虽然他会花费我一些时间去熟悉、适应,但是我依然很乐于这样做。

这就是我打算写本小篇幅的书来介绍它的原因。为了分享一下,在过去的十年中,当我在维护的过程中我是多么愉快的编写css的,并且同时是怎样提高效率的。曾经我也困惑过:Sass会不会令我不敢去尝试怎么使用它。最初,我担心我得完全改变我编写和管理样式表的方式。CSS有时是脆弱的,这是可以理解的,原因是其编写者或多或少出于对它的保护导致的。Can I get an amen?

现在,让我来向您展示如何让Sass不干扰你的工作流程,以及如何让您的工作更便利。下面,我将演示Sass的各个方面:怎样安装,怎样使用以及在项目中怎样提供给我们最大的帮助。但愿你将也会想我一样深深的爱上它的。

Sass逐步解说

是否需要每一处都要改变,比方说,你的样式表里需要换一套颜色,你必须要找到好几处地方,并且替换好几次颜色属性值。那么你希望这样处理css吗?

$brand-color: #fc3;
a {
 color: $brand-color;
}
nav {
 background-color: $brand-color;
}

如果你能够在只改变某一处的属性值,其他地方的属性也会随之相应改变?那么你可以使用sass!

或者是在整个样式表里,重复的风格在不同地点使用呢?

p {
 margin-bottom: 20px; 
 font-size: 14px; 
 line-height: 1.5;
}
footer {
 margin-bottom: 20px;
 font-size: 14px;
 line-height: 1.5;
}

岂不是很神奇?把那些共用的东西,规划成一个可重用块,只需要定义一次,然后引用到你需要的地方即可。

@mixin default-type {
 margin-bottom: 20px;
 font-size: 14px;
 line-height: 1.5;
}
p {
 @include default-type;
}
footer {
 @include default-type;
}

这也是Sass可以做到的,这两个非常简单的、几乎只是涉及点Sass皮毛的例子,向您展示了使用Sass编写的样式,是怎样把css样式写得如何更快,更容易,更灵活。这是在网页设计的世界里,一个非常受欢迎的助手。因为创建过一个网站的人都知道这样将会带来怎样的好处的…。

学习css的困难之处

真的面对它时,你会发现学习css也不是一件很容易的事。你要了解每个属性的作用、当他们层叠在一起时又是怎么工作的、在不同浏览器下支持什么属性与标签以及会出现一些怎样的怪异现象等等。这确实是一件不容易的事啊!再加上对一些复杂模块的反复维护,我们有必要这样做吗?可是很奇怪的是,居然有人还会当做一种享受(脑袋被门挤了吧…).

还有一个问题在于,CSS最初设计出来不是为了做我们今天做所做的这些事情的。由于浏览器的不断创新和CSS3的出现,极大的促进了css的发展的,并完全超出了其被设计出来的初衷(据说css被设计出来之初主要是用来布局的)。但是,现在我们依然需要依赖一些特殊技术来实现我们的目的,比如css hacks 就是其中的一种。再比如,我们想通过float属性来实现简单的图片与一段文本的对齐。就这种情况下,我们似乎更趋向于选择float属性来布局整个模块。

我们的样式表也极大地重复。颜色、字体都经常分组属性等。典型的CSS文件是一个非常线性的东西,使得面向对象的程序员抓破他们的脑袋也很难适应。(我不是一个面向对象编程的程序员,但我脑袋也快被抓破了。正如你可能读到)。

由于接口程序和web应用程序的更加健全化和更加复杂化,正如css正在做着最初被设计出来时从未想过做过的事情。这源于我们的想法总是这样的似乎可耻(css可不可以多做点别的呢?). 幸运的是, 浏览器制造商采用新的CSS特性还是比较快速的,更高效更强大的属性和选择器,解决今天的网络带来的新的需求问题。比如CSS3的一些特性:、高级选择器、新的布局选项、border-radius, box-shadow、transitions, transforms, animation等属性。这是多么的让人感到兴奋啊。然而,还有许多属性没有完全的得到支持,如果将来这些属性都被支持了的话,相信写css时会变的轻松的多了。

不重复原则

如果我们比较一下同行软件工程们的世界(我们比他们悠闲与舒适的多了),我们可以很快的看到他们是如何组织变量、常量、模块,等等,。他们用他们固有的,以及他们感觉非常必要的模式去为人们构建一些复杂的系统。

你也许听过不重复原则,它是由Andy Hunt 和 Dave Thomas在他们所著的一本叫《程序员修炼之道》的书里所定义出来的。据不重复原则的描述:

在一个体系中 ,每条知识必须有一个明确的,典型的代表。

不断地复制代码的方法可能会让开发者很困惑与感到失败(http://bkaprt.com/sass/2/)。因为常识是:我们只需写相同的代码段一次就够了,然后只需重用他们就行了。这才是比较有效、容易维护代码的方法。

css不遵守不重复原则。有时候,它充满了重复的规则、申明、属性等。在我们整个样式文件中,我们总是在不断地写着相同片段的代码。通过查看一个正规的css文件,“不重复软件“开发者将会哭的。首先他们会困惑,然后就是沮丧。

他们将会问:“你们是怎么维护其中的 !@#$ 的?“。

他们将会不耐烦的会回应:“我不是已经告诉过你了吗,这是IE的bug”。

为什么CSS这么难以处理?

通过一篇CSS发明者们所写过的文章,我们可以略微了解到, 这些年来CSS的一些语法局限(请参看的Bert Bos 所写的一些论述)。

文中大致是这样的说的:CSS突然停止,编程语言的程序员使用: 宏命令、变量、符号常量,条件变量表达式,等等更强大的功能。这是因为这些事情给开发人员带来了很多束缚.对缺乏经验的人来说,不经意的便会把自己弄晕,或者,更有可能的是,被吓坏了,以至于他们甚至不会碰CSS。这是一个平衡,CSS的平衡是不同于其他一些事情。

css的最初的设计者考虑到了它的可扩展性,他们明智的选择了希望更多的人能够一起创造、推动互联网的发展。他们希望css能够足够强大,能够做到网站风格的表现与内容相分离,并且很容易理解与使用。这一点我是非常赞同他们的。与此同时,对于怎样维护,我们还有很多事要做。这些事是很复杂、有着很微妙差别、很具有挑战性的。

幸运的是,有许多其他选择可以帮忙解决我们所遇到得为问题。其中sass就是一种。

什么是Sass

Sass是一个你所写的CSS样式表和css文件浏览器之间的预处理。Sass(Syntactically Awesome Stylesheets的缩写)弥补了css语言的一点不足之处。它允许你写css代码不需要重复。这对于创造可维护的样式将是非常有效的。

你可以在Sass网站上看到sass怎样描述它自身的简洁性的。

Sass是一种元语言的CSS,用它描述的文档具有干净风格和结构。与传统的css语法相比它能够做更多的事情。Sass都提供了一个更简单、更优雅的语法CSS,实现各种功能,是比较有用的管理css样式的一种新方式。

常规的css是不能够适应变量、mixin还有其他的好东西的,sass与其相比,sass提供了一种语法能够把一些强大的函数功能加入到你的css中去。然后它能通过一个命令行程序或某种web架构插件将该语法编译为常规的CSS文件。

更具体地说,Sass是CSS3的扩展,其SCSS(Sassy CSS)语法,稍微过一会,我们将讨论CSS3的超级集合。这意味着,任何有效的CSS3文件是有效SCSS文档。如果你有你一点点的css3的基础,对于Sass你可以很轻松的入门。你可以用他尝试着写一点东西试试看。这也意味着将一个现有样式表从CSS 变成SCSS可以分阶段完成,当你在学习和知道更多Sass的功能时。

不久之后,你将能够很流畅的使用Sass(它不会花费你太多时间的),感觉起来它就是一种专门为了css而生的扩展,它似乎填补了css本身的一些不足之处。这就是为什么当我一开始使用Sass之后就没有那种不爽的感觉,就像写css一样的爽。我想一旦你尝试着使用了它,你肯定也会无法自拔的。

而且,Sass还能够帮助我们的css代码写得更好。通过确认某些特性–目前不可能没有预处理程序的帮助下,给CSS书写者实际的实现和功能试验。如果它是合理的,某一Sass函数特性推动未来css的规范。

关于对Sass的误解与疑惑

我早前提到过。开始时我是很不情愿尝试Sass的,这是使用之前对他的一些误解导致的。我必须要知道ruby与其高级命令行?

我需要完全改变一下我以前写css的方式吗?Sass编译输出的css代码会臃肿吗?输出的代码可读性又是怎么样的呢?

幸运的是:以上所有疑惑都是多虑的。

当然了,我时常还是仍然能够在一些网络媒体渠道了解到一些人对他还是产生怀疑的。然我们来消除对它的一些误解吧。。。。

我害怕命令行怎么办!!!

我绝不是一个命令行专家,但也不算是菜鸟了吧!我不害怕遍历文件系统或使用Git命令。我同情那些不愿使用命令行的设计师和前端开发人员,他们或许有一点命令行恐惧症吧。然而实际上,对于Sass来说少量的命令行还是存在的,一些比较基本的一些命令行你还是要掌握的。

然而,有一些app应用与web框架可以避免命令行的使用(下一章我将向你们介绍)。所以呢,即使你不会使用命令行,也不要因它的存在而影响到你对Sass的学习。

我不想改变我写css的方式

这是由于对Sass的误会导致的。我特别在意样式表文件的设置与组织,引入了许多好东西在文档里面。但是请明确一下,SCSS语法是支持css3的,你不需要改变任何关于你写CSS的方式。注释、缩进等所有默认格式,可以保持不变在你的SCSS文档里。当我知道这样居然都可以时,我勒个去!那赶快学Sass吧!

我不想改变我设计的方式

另一方面,Sass不能解决你所有的问题或改掉你的一些不好的习惯。在css的工作过程中,如果没有好的规划与构思,即使你使用了Sass也一样会让你的代码感觉起来是那么的臃肿与低效。一个好的组织方式与构思方案,在Sass里面依然是很有用的。事实上,有时候,Sass可以把我们一些不好的方式极大的放大,可能也会让我们患上严重的错误。但是如果使用的恰当好处将会给我们的网站开发带来极大的便利。

好吧,,,既然现在我们已经详细了解了Sass,就让我们开始了解一些有趣的事吧。我相信你一定会惊叹Sass所能做的事的。

下一章节,我想为你们展示我们的工作流程,在流程中怎么让你快速适应他的,以及它怎样轻松的使用命令行与应用程序的。让我们开始使用sass吧。。。
<div

使用Sass创建弹性网格

express阅读(37)

<

div class=”entry-content clearfix”>

本文由大漠根据creativebloq.com的《Create flexible grids using Sass》所译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://www.creativebloq.com/web-design/create-flexible-grids-using-sass-9134524,以及作者相关信息

——作者:creativebloq.com

——译者:大漠

Steve Hickey阐述了如何使用CSS和Sass设计自己的弹性网格系统。在理解这篇文章需要具备以下几个方面:

  • 需要的知识:CSS,Sass和HTML基础
  • 需要的工具:Sass,代码编辑器
  • 项目时间:2~3小时

demo       download

如果你是一个设计师,或者你和设计师一起合作,你就会常碰到在一个网站中实现网格布局。这个过程可能非常痛苦,但保持视觉上和一个精心设计的网格一致性是非常值得的。

但当你为一个响应式设计写样式的时候,你并不想在布局中为每个元素计算宽度。相反,您需要一个可伸缩的解决方案,在你的网格中可以指定匹配的宽度。

我们可以使用一个像960网格系统来解决这个问题,但是在我看来,框架有很多问题,我们可以让这些问题不存在。

他们需要将大量的代码添加到你的样式文件中,如果你需要得新计算你所有的宽度,或者如果你想修改你的系统,他们依靠的是标记和没有语义的类名。这可能有很少代码被再次使用。


使用Sass创建弹性网格在一个web布局当中实现一个网格系统并不意味着你需要一个框架。这暗示着我们在本教程中需要构建的是一个网格系统。

框架提供的速度和一致性足以让我们容忍这些缺点,但我想我样可以做得更好。Sass可以用一些特性,让我们可以快速创建一个网格系统,可以在几秒钟内对网格系统进行修改,编译出必要的CSS,使我们能在我们的标记中消除无义语化的类名。

设计一个好的网格系统

任何网格需要足够的内容来支持项目,但并非如此复杂,以至于使用变得笨拙。原因之一就是960网格系统已经非常的流行,允许划分大量同样的列,可以很容易的适应大多数内容的要求。这很重要,因为很多变量会影响一个网格系统。

在未来,媒体断点和行高和body中文本行高都将影响一个网格元素之间的间距和比例。

真正优秀的网格设计细节超出了本文的范围,但有一些工具可以帮助您入门。

我建议您看看Modular Grid PatternGridulator

我个人使用的是Gridulator,因为它会为你计算网格的最大宽度和为列提供各种列宽度和间距。主要的缺点是它不会计算流体网格所需的百分比,但对于工具而言是一个常见的问题。在本教程中,我们将把这些值实现成百分比值。


使用Sass创建弹性网格Elliot Jay Stock的简单的响应式Photoshop网格形成了我们的网格系统的基础。

对于本教程,我们将使用Elliot Jay Stocks的《Responsive Photoshop Grid》一文中介绍的,因为所使用的比例计算很容易理解。它的系统是基于六列网格,每列宽度为150px,相邻两列的间距为20px,网格总宽度为1000px。这些宽度的百分比,我们将使用Ethan Marcotte创建的伸缩性网格设计公式

target /  context = result

在这种情况下,我们的target=150pxcontext=1000px。根据这个公式,应该像这样:

150 / 1000  = 0.15

当这个结果转换为一个百分比时,我们的列的宽度为15%。使用相同的公式,应用到我们的列间距20px上,得出的值为2%。

在这一点上,你应该明白为什么我们使用Elliot的网格。我们不会有任何的长的十进制值的百分比宽度,这将它更容易专注于更重要的概念。

(当使用其他的网格系统,会具有抵抗长十进制值的冲动。提供适应的宽度时,浏览器计算会做得更好。提供越长的值,浏览器计算的时间越长。)

简洁的模板

接下来,让我们来看结构。我们要构建一个Web页面来演示该系统的各种特性。从下载的文件中,你可以打开01-markup目录中的index.html文件。

我们的结构开始使用的HTML5 Boilerplate project的结构,但为了简便起见,我们放弃了一些元素。

在这里,你大叫“有语义化类名”时看看。这些类是演示代码中的命名,因此事实上,他们是具有语义化的。你会看到当我们开始编写Sass时,其他的类名同样的好用。

<!doctype html>
<head>
    <title>Flexible Grid Tutorial</title>
    <meta name="viewport" content="width=device-width">
    <link rel="stylesheet" href="css/styles.css" />
</head>
<body>

<div class="container">
    <header role="banner">
        <h1>Flexible Grid Tutorial</h1>
    </header><!-- end of header[role="banner"] -->

    <div role="main">
        <section class="hero"></section><!-- end of section.hero -->

        <section class="two-columns">
            <h2>Two Columns</h2>
            <div class="left-column"><p>Lorem ipsum dolor sit amet...</p></div>
            <div class="right-column"><p>Lorem ipsum dolor sit amet...</p></div>
        </section><!-- end of section.two-columns -->

        <section class="six-columns">
            <h2>Six Columns</h2>
            <div class="first-column"><p>Lorem ipsum dolor sit amet...</p></div>
            <div class="second-column"><p>Lorem ipsum dolor sit amet...</p></div>
            ...

每一个大型网格背后都隐藏着巨大的代码。我们这里算不错了,干净,一些空标签只是用来做演示使用。

创建Sass文件结构

我们像Ruby on Rails应用程序处理样式表一样,组织Sass文件。这种结构允许我们很明显的组织我们的代码,但仍然只编译一个CSS文件。

css/sass/styles.scss文件输出css/style.css文件,将以下种结构组织文件:

@import "variables";//全局变量,他们首要访问的变量
//其他样式
@import "mixins";//将样接近的样式,使用变量定义一个全局的mixins
@import "typography";//创建基本的排版系统
@import "grid";//网格系统的函数和mixin都将在这里定义
@import "global";//全局最后定义的样式规则,这样可以使用前面所有的样式

通常,重置样式表在导入mixins样式之后导入。

样式变量,Mixins和类型规则

接下来,打开你下载文件中的03-base-styles目录中的css/sass/_variables.scss文件。这些都是本教程中将要使用的基本变量。我们使用//单行添加注释,因为这些规则在编译出来的CSS中不会编译出来。指定给网格的变量都在grid样式表中定义。

如果你在相同的目录中打开css/sass/_mixins.scss文件,你可以看到用于网格系统的mixin。因为他们除了使用于网格系统之外还可能被定义在全局范围使用。

根据Paul Irish的主张,我们要用box-sizing:border-box来简化网格计算。(如果你的项目需要支持IE7以及IE7之下浏览器,他的文章链接接到一些适当的解决方案)。

最后,打开css/sass/_typography.scss文件。这些规则是绝对是支持本教程中使用的元素。文档中的注释标明了样式的规则。


使用Sass创建弹性网格我们使用易于理解的方式组织我们正在使用的文件结构,但仍编译到一个样式表中。

定义伸缩性网格函数

现在,我们都设置好了,我们可以看到有趣的部分。我们要做的第一件事情在我们的网格样式表(打开04-grid-functions目录中的css/sass/_grid.scss文件)中声明一些用于网格功能的变量。这些都是基于设计网格系统计算所需的变量。

$max-width: 1000px; //设置页面的最大宽度
$column-width: 15%; //设置列的列宽度
$gutter-width: 2%; //设置列与列之间的间距
$maximum-columns: 6; //设置最大的列数

接下来,我们使用函数创建伸缩性的列和间距宽度。这些函数是从Bourbon的mixin中修改得来的。我们将引入创建我们的网格系统所需的mixin和修改变量的命名,更好的支持我们创建的函数功能。

@function columns($columns,$container-columns:$maximum-columns) {
    $width: $columns * $column-width + ($columns - 1) * $gutter-width;
    $container-width: $container-columns * $column-width + ($container-columns - 1) * $gutter-width;
@return percentage($width / $container-width);
}
@function gutter($container-columns: $maximum-columns, $gutter:$gutter-width) {
    $container-width: $container-columns * $column-width + ($container-columns - 1) * $gutter-width;
@return percentage($gutter / $container-width);
}

在我们全局样式中,可以使用这些函数来设置元素的宽度(width)和外边距(margin)。作为一个例子,让我们看看下面的代码:

div.parent {
    width: columns(3);
    margin-right: gutter;
div.child {
    width: columns(1,3);
    margin-right: gutter(3);
}
}

编译出来的CSS:

div.parent {
    width: 49%;
    margin-right: gutter;
}
div.parent div.child {
    width: 30.61224%;
    margin-right: 4.08163%;
}

columns函数至少需要一个参数,它才能正常工作,这就是我们希望该元素的列数。它会基于列数和间距计算元素的宽度。它接受一个可选参数(第二个参数),应用样式的元素是嵌套在另一个元素内。因为计算百分比宽度要根据父元素的宽度,所以我们需要调整我们的子元素上使用的百分比进行补偿。通过提供的跨父元素的列距做为第二个参数,我们Sass函数将重新计算所需的百分比宽度,并相应的调整。


使用Sass创建弹性网格非常基本的样式应用我们的模板中。我们现在准备开始有趣的教程:设置网格函数。

gutter函数的工作方式也是类似的。如果我们不提供一个参数,它不会执行任何调整。当它给一个嵌套的元素做声明时,我们需要为其提供一个参数,指定它的父元素的跨列的宽度和间距来做计算。

支持mixins

现在我们可以为响应式计算列的宽度和间距。但是让效果有用之前,我们仍然需要更多的样式用于其他元素上。

一般来说,创建一个网格框架,使用.row来包裹列。如果他存在,可以适用于父元素,或者一个添加了这个类的div容器。


使用Sass创建弹性网格现在我们的布局完全是弹性的。我们将加点工作扩展这个网格,以适应不同的用例。

我们要给他创建一个mixin,被包含在父元素中。这仍然可以应用于容器div中,但为了阻止添加表象的标记,可以把他作为mixin嵌套到一个类中。mixin row需要横跨整个容器的宽度,没有内距,而且里面也必须清除浮动。

@mixin row {
    width: 100%;
    max-width: $max-width;
    margin: 0 auto;
@include clearfix;
@include nesting;
}

row的mixin包了一个清除浮动的clearfix的mixin,还包括了一个nesting的mixin,清除内距padding。所以嵌套的列可以填满整个容器,并且让子元素浮动和有一个适应的列间距。我们还将在这里设置一个border-box属性。以后,如果我们需要支持的不只是一个div元素,我们可以将他们添加选择器中。这个mixin可让包含在元素内的任何元素在网格系统中对齐。

@mixin nesting {
    padding: 0;
  & > div {
      float: left;
      margin-right: gutter();
  @include border-box;
  }
}

我们也希望我们的网格系统支持列的偏移,因为空白的空间是个好东西,我也想这样使用。当我们想要让一个元素进行偏移时,我们将在我们的样式表中使用一个offset的mixin。他将接受两个参数:一个是元素偏移的方向和元素偏移所占的列数。我们还定义了一个offset-columns函数,用来计算元素偏移量。

@function offset-columns($columns) {
    $margin: $columns * $column-width + $columns * $gutter-width;
@return $margin;
}
@mixin offset($from-direction, $columns) {
    @if $from-direction == left {
        float: left;
        margin-left: offset-columns($columns);
    }
    @if $from-direction == right {
        float: right;
        margin-right: offset-columns($columns);
    }
}

行中让人讨厌的最后一个列元素

我们需要为每一行中最后一个元素做进一步的处理。如果不删除其margin-right的值,元素会挤到他相邻的元素。有几种解决方案可以解决这个问题,不幸的是这些解决方法都是CSS的新特性,低版本的IE浏览器不兼容。

第一种方式是在我们的nesting的mixin中添加:last-child选择器。这种方式,可以删除最后一个元素的margin-right值。

不幸运,这种方式在IE8以下浏览器不被支持。

另一个解决方案是使用:first-child选择器。把所有列的margin-rightmargin-left代替,并且使用:first-child选择器,删除第一列的margin-left的值,这样我们也能实现相同的结果。

但先别太高兴了。我们不是要在一个容器里删除第一个或最后一个元素的margin。我们试图在任何行中删除第一个或最后一个元素的margin值。我们不想在结构中添加一个div容器里来实现这一目标,所以:first-child就出容器了。

下一个更合乎逻辑的解决方案是使用:nth-child()选择器,它可以完美的实现这一目标,但也像:last-child一样在IE低版本浏览器中不被支持。下面进入我们的解决方案:定义mixin。


使用Sass创建弹性网格百分比宽度不总是转为人整数像素,在一些浏览器中会有一些错误。我们可以将最后一个元素向右浮动来解决这个问题。

在大多数网格框架中都会有一个.last.end类名,其唯一的目的是为了消除margin。仅从责任的角度来看,这是完美的,但它也将需要将类名添加到结构中。然而,我们可以使用它作为一个mixin,而不是一个类,我们可以在我们的样式中将它应用到更具语义化的类名里。这种方法虽然没有:nth-child()选择器那样优越,但也是可以解决问题的。

@mixin last {
    margin-right: 0;
    float: right;
}

我们在last的mixin中定义元素向右浮动,并且设置margin-right值为0。这里隐藏了一个如何计算百分比的问题。基本上,百分比并不能像像素一样精确计算,因为不同的浏览器引擎对些计算略有不同。

合并在一起

现在,我们有了自适应网格系统的功能,我们可以将它们应用于我们的结构中。我们先给body元素和容器设置基本样式。

body {
    padding: 0 1em;
    margin: 0;
}
.container {
    width: 100%;
    max-width: $max-width;
    margin: 0 auto;
    padding: 0;
}

body元素设置左右内距(padding)为1em,让我们的内容在小型设备上留有一定的空间。你们注意到,虽然有很多相同的样式,我们并没有在容器中使用@mixin row。这是因为我们不想@mixin row的子选择器受影响。我们很舒服,不用重复写代码,因为它只会用在一个地方,这些都是常见的样式,并且只适用于一个容器元素。

接下来,我们会让一些区域就像行,给包含的元素设置一些基本的列样式。

.two-columns,
.six-columns,
.varying-columns,
.nested-columns,
.more-nested-columns,
.offset-columns {
@include row;
}

最后,我们可以给元素定义一些自己的样式。这些都可以基于flexible-columnflexible-gutter函数和任何有必要的@mixin nesting。在这里,我们没有空间放置所有需要的代码,但你可以在我们的05-final目录中查看css/sass/_global.scss文件。


使用Sass创建弹性网格我们不仅创建一个自适应的网格布局系统,而且还可以很轻松的修改适用于任何用例。

注意,在实际生产代码,应该会有一些更有效的Sass代码,但在本教程中,我们使用的是在每个元素声明,说明他们的使用。

结束

让我们回顾一下我们所做的。我们开始通过设计一个响应式网格系统并生成所需的分比宽度值。然后,我们创建一个简洁的模板和一个没有太多类名的演示页面。建立我们网站目录后,我们使用Sass编写高效、可维护的所需的代码。然后我们创建必要的函数功能和mixin,生成列和间距的宽度、处理嵌套和列的偏移以及处理容器中每行的最后一列。最后我们应用这些功能在我们的全局样式中,使我们能够把我们页面的元素在网格系统中对齐。

最重要的是,在这里创建的网格功能可以在网格样多表中通过改变变量用于新项目中。总之,我们已经为我们的下一个项目建立了一个网格系统。

demo         download

译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!
<div

大前端WP主题 更专业 更方便

联系我们联系我们