上一篇文章介绍了怎样使用compass
合并雪碧图,生成的icons.css
文件中单位是px
,PC端能够直接在html文件中使用,但在移动端,咱们须要根据不一样分辨率的屏幕,来缩放图片大小,显然使用px
单位确定是不行的。因此须要作一下单位转换的工做。css
移动端使用rem
做为单位是最合适不过了。并非使用了rem
就能够,还须要作一些准备工做。咱们都知道rem
是基于html
标签的font-size
的,因此须要使用js动态的计算html
的font-size
。这里我使用淘宝的lib-flexible
。html
在上一篇文章中,有讲过雪碧地图(Sprite maps),以下面:git
$icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart); .icon { width: image-width(sprite-file($icons, card-icon)); height: image-height(sprite-file($icons, card-icon)); background-image: sprite-url($icons); }
生成css:github
.icon { width: 77px; height: 64px; background-image: url('/images/icons-s37f950be3b.png'); }
如今,须要把px
转换成rem
。咱们不可能在icons.css
中转换,应该在icons.scss
文件中转换。函数
在icons.scss
声明一个转换函数px2rem
,:flex
@function px2rem ($px) { @return $px / 64px * 1rem; }
这里的64
是由于视觉稿是640px
的,若是是750px
的就是75
。能够看一下lib-flexible
的说明。url
加上转换函数的icons.scss
文件是这样的:spa
$icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart); @function px2rem ($px) { @return $px / 64px * 1rem; } .icon { width: px2rem(image-width(sprite-file($icons, card-icon))); height: px2rem(image-height(sprite-file($icons, card-icon))); background-image: sprite-url($icons);; }
生成的css
以下:命令行
.icon { width: 1.20313rem; height: 1rem; background-image: url('/images/icons-s37f950be3b.png'); }
好了,第一步转换工做就完成了。咱们都知道,使用雪碧图,确定要使用background-position
属性,它的单位也是px
,也须要转换,因此须要在icons.scss
加上:code
$icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart); @function px2rem ($px) { @return $px / 64px * 1rem; } .icon { width: px2rem(image-width(sprite-file($icons, card-icon))); height: px2rem(image-height(sprite-file($icons, card-icon))); background-image: sprite-url($icons); background-position: px2rem(sprite-position($icons, car-icon)); }
可是,编译的时候出错了,错误以下:
意思就是:background-position
的值为-250px 0
,并不能简单的使用px2rem
函数,那该怎么办?咱们先来判断一下传递给函数的参数的类型:
@function px2rem ($px) { @warn type-of($px); @return $px / 64px * 1rem; }
再次编译(能够使用compass watch
进行监听文件的修改),命令行提示以下图:
从图中能够知道:$width
、$height
的类型是number
,而$pos
类型是list
。知道了什么类型就能够对症下药了,修改函数以下:
@function px2rem ($px) { @if (type-of($px) == "number") { @return $px / 64px * 1rem; } @if (type-of($px) == "list") { @return nth($px, 1) / 64px *1rem nth($px, 2) / 64px * 1rem; } }
nth
方法能够取出list
中的每一项进行运算,输出css以下:
.icon { width: 1.20313rem; height: 1rem; background-image: url('/images/icons-s37f950be3b.png'); background-position: -1.46875rem -1.40625rem; }
这边又会有个问题:background-position
的值有多是0 0
、0 100px
或者100px 0
,而0
是没有单位的,这样转换的时候会报错,继续对px2rem
函数进行改造,以下:
@function px2rem ($px) { @if (type-of($px) == "number") { @return $px / 64px * 1rem; } @if (type-of($px) == "list") { @if (nth($px, 1) == 0 and nth($px, 2) != 0) { @return 0 nth($px, 2) / 64px * 1rem; } @else if (nth($px, 1) == 0 and nth($px, 2) == 0) { @return 0 0; } @else if (nth($px, 1) != 0 and nth($px, 2) == 0) { @return nth($px, 1) / 64px * 1rem 0; } @else { @return nth($px, 1) / 64px *1rem nth($px, 2) / 64px * 1rem; } } }
上面对各类为0
的状况进行了判断,避免了错误。
下面还须要对background-size
属性进行转换。在PC端若是图片不要缩放的话,其实不须要该属性,但在移动端通常是须要的。在移动端,可能不少人不知道该怎么用background-size
属性,究竟是设置整个雪碧图的大小,仍是设置单个sprite的的大小呢?实际上是设置整个雪碧图的大小。
好像compass
没有内置的方法得到雪碧图的大小,不要紧,咱们能够等到雪碧图生成的时候,再去查看雪碧图的大小。能够先用两个变量保存雪碧图的宽高,初始化为0
:
$bigWidth: 0; $bigHeight: 0;
等雪碧图生成后,查看图片大小,再修改,如:
$bigWidth: 242px; $bigHeight: 270px;
这时icons.scss
文件内容以下:
$icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart); $bigWidth: 242px; $bigHeight: 270px; @function px2rem ($px) { @if (type-of($px) == "number") { @return $px / 64px * 1rem; } @if (type-of($px) == "list") { @if (nth($px, 1) == 0 and nth($px, 2) != 0) { @return 0 nth($px, 2) / 64px * 1rem; } @else if (nth($px, 1) == 0 and nth($px, 2) == 0) { @return 0 0; } @else if (nth($px, 1) != 0 and nth($px, 2) == 0) { @return nth($px, 1) / 64px * 1rem 0; } @else { @return nth($px, 1) / 64px *1rem nth($px, 2) / 64px * 1rem; } } } .icon { width: px2rem(image-width(sprite-file($icons, card-icon))); height: px2rem(image-height(sprite-file($icons, card-icon))); background-image: sprite-url($icons); background-position: px2rem(sprite-position($icons, card-icon)); background-size: px2rem(($bigWidth, $bigHeight)); background-repeat: no-repeat; }
生成css
以下:
.icon { width: 1.20313rem; height: 1rem; background-image: url('/images/icons-s37f950be3b.png'); background-position: -1.46875rem -1.40625rem; background-size: 3.78125rem 4.21875rem; background-repeat: no-repeat; }
到这里,应该能够说是很完美了,但还有改进的空间。咱们须要自定义不少类,如:
.icon1 { width: px2rem(image-width(sprite-file($icons, card-icon))); height: px2rem(image-height(sprite-file($icons, card-icon))); background-image: sprite-url($icons); background-position: px2rem(sprite-position($icons, card-icon)); background-size: px2rem(($bigWidth, $bigHeight)); background-repeat: no-repeat; } .icon2 { width: px2rem(image-width(sprite-file($icons, watch-icon))); height: px2rem(image-height(sprite-file($icons, watch-icon))); background-image: sprite-url($icons); background-position: px2rem(sprite-position($icons, watch-icon)); background-size: px2rem(($bigWidth, $bigHeight)); background-repeat: no-repeat; } ......
上面的每一个类中的属性都是同样的,为何不使用一个mixin
,把相同的属性都放进这个mixin
中,而后在每一个类中引入就能够了。下面来定义一个mixin
:
@mixin sprite-info ($icons, $name) { width: px2rem(image-width(sprite-file($icons, $name))); height: px2rem(image-height(sprite-file($icons, $name))); background-image: sprite-url($icons); background-position: px2rem(sprite-position($icons, $name)); background-size: px2rem(($bigWidth, $bigHeight)); background-repeat: no-repeat; }
使用这个mixin
:
.card { @include sprite-info($icons, card-icon); } .watch { @include sprite-info($icons, watch-icon); }
生成css以下:
.card { width: 1.20313rem; height: 1rem; background-image: url('/images/icons-s37f950be3b.png'); background-position: -1.46875rem -1.40625rem; background-size: 3.78125rem 4.21875rem; background-repeat: no-repeat; } .watch { width: 1.3125rem; height: 1.40625rem; background-image: url('/images/icons-s37f950be3b.png'); background-position: 0 0; background-size: 3.78125rem 4.21875rem; background-repeat: no-repeat; }
如今能够说是很是完美了。下面贴出icons.scss
文件中最终的代码:
$icons: sprite-map("icons/*.png", $spacing: 8px, $layout: smart); $bigWidth: 242px; $bigHeight: 270px; @function px2rem ($px) { @if (type-of($px) == "number") { @return $px / 64px * 1rem; } @if (type-of($px) == "list") { @if (nth($px, 1) == 0 and nth($px, 2) != 0) { @return 0 nth($px, 2) / 64px * 1rem; } @else if (nth($px, 1) == 0 and nth($px, 2) == 0) { @return 0 0; } @else if (nth($px, 1) != 0 and nth($px, 2) == 0) { @return nth($px, 1) / 64px * 1rem 0; } @else { @return nth($px, 1) / 64px *1rem nth($px, 2) / 64px * 1rem; } } } @mixin sprite-info ($icons, $name) { width: px2rem(image-width(sprite-file($icons, $name))); height: px2rem(image-height(sprite-file($icons, $name))); background-image: sprite-url($icons); background-position: px2rem(sprite-position($icons, $name)); background-size: px2rem(($bigWidth, $bigHeight)); background-repeat: no-repeat; } .card { @include sprite-info($icons, card-icon); } .watch { @include sprite-info($icons, watch-icon); }
生成的icons.css
代码以下:
.card { width: 1.20313rem; height: 1rem; background-image: url('/images/icons-s37f950be3b.png'); background-position: -1.46875rem -1.40625rem; background-size: 3.78125rem 4.21875rem; background-repeat: no-repeat; } .watch { width: 1.3125rem; height: 1.40625rem; background-image: url('/images/icons-s37f950be3b.png'); background-position: 0 0; background-size: 3.78125rem 4.21875rem; background-repeat: no-repeat; }