概要:介绍Compass如何让你从本地开发原型轻松转移到正产环境的网址或Web应用中。
本章内容:
● CSS精灵的历史和基本原则
● Compass混合器让精灵自动化
● 自定义精灵图片和CSS输出的高阶技巧
1.精灵的工作原理
在早期,CSS精灵是很简单的。设计师们会把按钮的不同状态做成图片,并把它们做成一张单个图片。然后在CSS里,他们会设置按钮的宽、高以及背景图片的属性,并在不同的状态下改变背景图的位置。如下代码:
.go-button { width : 75px ; height : 45px ; background : url(‘images/sprite-button-usage.png’) top left ; } .go-button : hover{ background-position : center ; } .go-button : active { background-position : right ; }
当这项技术第一次流行起来时,大多数的文章都把它视为解决浏览器每次获取下一张图片界面都会闪烁的好方法,仿佛这就是它的优势所在。其实不然,闪烁仅仅是Web性能中看得见的比较明显的一部分,而精灵的使命是解决真正的问题。
2.精灵的必要性
为了理解精灵真正解决的问题,你需要知道浏览器下载每张图片时究竟做了什么。
2.1 HTTP请求越少越好
每次你的浏览器需要从服务器下载一个文件时,都不得不走完一系列的步骤。我们用最简化的方式把它们列出来:
● 浏览器——请求服务器打开一个传输套接字
● 服务器——处理请求并作出回应
● 浏览器——确认服务器的回应
● 浏览器——从服务器请求数据
● 服务器——处理请求
● 服务器——查询文件
● 服务器——初始化文件传输
● 浏览器——接受文件传输
你的浏览器即便得到的是很小的一段数据,都会和服务器走完所有的流程。所以即使是一张很小的已经压缩过的图片,下载这个图片之前在网络上的琐碎时间开销都是不可避免的。
使用CSS精灵可以明显减轻Web服务器压力。它不仅仅是一个好方法,更是高流量站点的最佳实践和必要措施。
2.2 手动处理是一种折磨
确实,精灵图片能够明显提升网站的加载时间,但是每改变一张图片,你就不得不更新这张精灵地图。如果需要改变图片的尺寸,你就必须移动周围的图片,并引发其他一系列图片位置的改变,你需要重新测量每张图片,再将其更新到你的样式表中。
2.3 Compass的方案
因为Compass已经集成到了你的样式表撰写流程中,所以它是生成CSS精灵的理想搭档。你在第7章将会看到,Compass有一个配置文件用来说明网站图片所在的位置,因为Compass会生成你的CSS,所以它是自动化处理精灵的理想搭档。
Compass生成的精灵的过程如下:
● 让Compass指向一个精灵的文件夹;
● 告诉Compass撰写你的精灵的CSS;
● 编译你的样式表。
通过两行Sass,你就可以告诉Compass根据一个目录下的每张图片生成精灵,测量它们的尺寸,通过每个图片的文件名撰写出不同类名下的背景图片。当你改变图片时,Compass会自动更新你的样式表,生成一个新的精灵并在必要的情况下更新背景位置。
3.用Compass制作精灵
目前的Compass只生成PNG精灵文件。因为PNG是最理想的精灵格式。
3.1 创建一个精灵地图
为了将文件内的图片转为一张精灵地图,打开screen.scss并加入如下所示代码:
@import “compass/utilities/sprites”; @import “icons/*.png”;
首先,你导入了Compass的精灵模块。然后,你使用一个精灵导入语句告诉Compass根据images/icons/目录下的所有PNG图片生成一张精灵地图。
3.2 生成精灵的CSS
Compass有两个很顺手的混合器,可以为你自动生成精灵的CSS,如下代码所示:
@include all-<map>-sprites ; @include <map>-sprite($name) ;
这里的<map>是一个占位符,它会被替换为包含精灵图片的文件夹的名称。all-sprites混合器会为整个精灵地图撰写所有必要的CSS。而第二个混合器将会输出一个独立命名精灵的CSS。这两个混合器都会随着精灵的导入而创建,因此它们只能在导入之后使用。
(1)all-sprites混合器
@import “compass/utilities/sprites”; @import “icons/*.png”; @include all-icons-sprites ;
这个all-icons-sprites混合器将会为精灵地图中的每个精灵撰写必要的CSS,如下代码:
.icons-sprite , .icons-arrow , .icons-attachment , .icons-box-add , ... { background : url(‘/images/icons-s0cad3f8f97.png’) no-repeat ; } .icons-arrow { background-position : 0 0 ; } .icons-attachment { background-position : -16px -96px ; } .icons-box-add { background-position : 0 -64px ; } ...
现在让我们看看这个混合器都生成了什么:
● 它为设置所有来自images/icons/的精灵样式创建了一个基础类icons-sprite ;
● 它为其精灵目录下的每一个文件名创建了类;
● 它为所有的精灵都增加了背景图片;
● 它为所有的精灵都增加了背景位置。
默认情况下,Compass不会设置这些元素的宽和高。Compass可以自动生成精灵的尺寸,但我们不一定总需要它。要在项目中使用这个CSS,你可以添加这些精灵类至HTML标签,或者你更愿意使用@extend从精灵类继承属性,如下代码:
.add-button { @extend .icons-box-add ; }
(2)single-sprite混合器
使用single-sprite混合器:
@import “compass/utilities/sprites”; @import “icons/*.png”; .add-button { @include icons-sprite(box-add) ; }
这将会输出这个元素样式必要的CSS,代码如下:
.icons-sprite , .add-button { background : url(‘/images/icons-s0cad3f8f97.png’) no-repeat ; } .add-button { background-position : 0 -358px ; }
有了single-sprite混合器,就没有必要生成一个类名了,因为样式已经包含在了选择器里。当Compass添加background-image和background-position样式时,会直接使用这些选择器,在这个例子里是 .add-button。相比简单方便的all-sprites混合器,这个方式生成更少的CSS,也让你对输出有更多的控制。
4. 配置Compass精灵
Compass使用包含导入图片的文件夹的名称来命名这些配置变量、混合器和函数。在前面的例子中,你从一个名叫”icons”的文件夹导入了精灵,而这正是all-icons-sprites混合器名字的来源。如果你从嵌套文件夹导入了精灵,那么Compass会使用最末端的包含精灵的文件夹名。所以@import “sprites/social/*.png”; 会将”social”用于其变量名、混合器和函数名中。
4.1 自定义精灵地图
你可以自定义一个精灵地图或通过其配置变量有针对性地定义精灵。影响整个精灵的图的变量的名称以地图名称开头,而仅改变整个精灵的变量的名称是地图名紧跟精灵文件名,如下代码所示:
$<map>-<property> : setting ; $<map>-<sprite>-<property> : setting ;
在我们的示例项目中,精灵文件夹的名称是”icons”,所以改变间距的变量被命名为$icons-spacing。而为了设置icons/attachement.png间距变量,你应该赋值给$icons-attachmeng-spacing。
记住,这些变量必须在导入精灵之前被定义,否则不会生效。
(1)配置精灵间距
Compass允许你通过配置精灵间距变量改变精灵的间距:
$<map>-spacing : 0px ; $<map>-<sprite>-spacing : 0px ;
默认值是0px,这意味着每个精灵被拼入精灵地图时不带任何间距。设置这个变量或单独给每个精灵赋值,会使得每个精灵在拼合时在周围增加若干像素的透明间距。如下代码:
$icons-spacing : 4px ; $icons-arrow-spacing : 12px ;
这就意味着你为icons精灵地图中每个精灵设置了4个像素的透明间距,并单独为arrow精灵设置12像素的透明间距。
(2)设置精灵的重复性
在一些情况下,精灵地图中水平方向的重复精灵会有大用处。为此,你可以设置精灵的重复性变量:
$<map>-repeat : no-repeat/repeat-x ; $<map>-<sprite>-repeat : no-repeat/repeat-x ;
其默认值是no-repeat,但是你可以将其改为repeat-x使其在整个x轴平铺。代码如下:
$icons-arrow-repeat : repeat-x ;
(3)设置精灵的位置
有时候,移动一个精灵的位置是非常有帮助的。Compass允许你通过设置位置变量来横向移动图片:
$<map>-position : 0px ; $<map>-<sprite>-position : 0px ;
设置精灵的位置:
$icons-position : 4px ; $icons-arrow-position : 100% ;
在这个例子中,图标精灵地图中的每个精灵都被右移了4个像素,并且箭头精灵移动到了最右边。
(4)设置精灵地图的布局
Compass有以下几种精灵的布局可供选择:
$<map>-layout : vertical/horizontal/diagonal/smart ;
默认的布局是vertical,从整体上影响精灵地图布局,告知Compass如何排布所有的精灵。大多数情况下,你可能更需要将布局设置为smart,这种布局会让Compass产生最小的空白区域。
(5)清除过期的精灵地图
当添加、删除或改变图片后,会生成新的精灵地图。Compass会自动为你一处旧的精灵地图,或者你也可以把它们保存下来:
$<map>-clean-up : true/false ;
默认情况下,当生成新的精灵地图时,Compass会自动把旧的移除。
4.2 自定义精灵的CSS
你已经知道Compass在精灵地图中布置图片是多么方便。尽管这些精灵地图的改变必然会影响Compass最终生成的CSS,这里还是有一些办法让你直接自定义生成的CSS。
(1)输出精灵的尺寸
如果你想要给一个特殊的精灵设置尺寸,你可以使用精灵尺寸的辅助器:
<map>-sprite-height($name) <map>-sprite-width($name)
这里有两个函数可以让Compass测量原始精灵的尺寸并将其输出以便你在样式表里使用它。通过使用这些辅助器函数,你可以设置单个精灵的宽和高。例如下面这段代码:
@import “icons/*.png”; .next { @include icons-sprite(arrow) ; width : icons-sprite-width(arrow) ; height : icons-sprite-height(arrow) ; } .add-button{ @include icons-sprite(box-add) ; }
另外,如果你想要为精灵地图中的每个精灵自动设置尺寸,你可以为这个精灵地图设置一个配置变量。
$<map>-sprite-dimensions : true/false ;
默认值是false,将其设置为true会测量每张精灵图片并为其精灵类的宽和高赋值,如下代码所示:
$icons-sprite-dimensions : true ; @import “icons/*.png”; .next { @include icons-sprite(arrow) ; }
生成带精灵尺寸的CSS:
.next { background-position : 0 -70px ; width : 32px ; height : 32px ; } .add-button { background-position : 0 -358px ; width : 32px ; height : 32px ; }
(2)精灵的基础类
Compass可以方便的通过生成一个基础类为每一个精灵应用普通样式。你可以设置基础类变量来选择你的所属类名称:
$<map>-sprite-base-class : “.class-name”;
当你使用全部精灵或单独精灵的混合器时,Compass会输出一个精灵的基础类,并且其选择器还会串联所有设置了background-image属性的选择器。
改变精灵的CSS基础类:
$icons-sprite-base-class : “.sprite-mcspriterson”; @import “icons/*.png”; .spritey-mcspriterson { overflow : hidden ; } .next { @include icons-sprite(arrow) ; }
每个精灵类都扩展了基础类。所以你添加到基础类的任何样式都会影响你的每一个精灵。如下代码生成自定义基础类的CSS:
.spritey-mcspriterson , .next { background : url(“/images/icons-s0cad3f8f97.png”) no-repeat ; } .spritey-mcspriterson , .next { overflow : hidden ; } .next { background-position : 0 -70px ; }
记住,输出的CSS中仅有基础类发生改变。变量名、函数和混合器依然是相同的,它们的名字源于精灵地图的文件夹。
(3)魔术精灵选择器
Compass可以通过伪选择器自动生成精灵的CSS,但是如果需要的话,你可以禁用它:
$disable-magic-sprite-selectors : true/false ;
魔术精灵选择器是默认开启的,也就是说Compass在精灵时,会根据以”_hover””_active”或”_target”结尾的名字自动输出CSS的:hover、:active和:target伪选择器。
例如,你想要为正常和悬停状态设置不同的精灵,那么就在你的精灵文件夹中加入arrow.png和arrow_hover.png,Compass就会为悬停的伪类生成CSS精灵的背景,如下代码所示:
.next { background-position : -32px 0 ; } .next : hover , .next . arrow-hover { background-position : -48px -96px ; }
如果魔术伪选择器和你选择的图片命名表冲突,请设置为true从而对所有精灵地图禁用这个功能。
5. 驾驭精灵辅助器
5.1. 创建精灵地图
如你早些时候看到的,创建一个特定输入的精灵地图,如@import “icons/*.png”;,并不仅仅是创建了一个精灵地图;它还为精灵地图和每个精灵设置了混合器和变量。如果你使用精灵辅助器,就不必使用这些变量和混合器,否则会造成精灵导入的大材小用。取而代之的是sprite-map辅助器。
$icons : sprite-map(“icons/*.png”, $layout : smart ) ;
它会创建一个智能布局的精灵地图,并把精灵地图的图片URL赋值给$icons变量。我们稍后会在其他的辅助器里用这个变量生成CSS,如下代码:
$icons : sprite-map (“icons/*.png”, $arrow-spacing : 5px ) ;
任何精灵地图或单独精灵地图属性都可以配置,仅使用我们早些时候提到的去掉<map>间的配置变量。你可以使用$repeat替代$<map>-repeat的重复性配置;也可以使用$arrow-repeat替代$<map>-<sprite>-repeat,这里的”arrow”是你配置的精灵的名称。
5.2 撰写精灵的CSS
在Compass为你生成精灵地图之后,你仍然需要写出每个精灵的CSS。为此,我们将转向一些其他的辅助器和混合器。
(1)sprite辅助器
Sprite辅助器使得撰写精灵的CSS非常简单:
sprite( $map , $sprite , [$offset-x] , [$offset-y] )
sprite辅助器需要精灵地图、精灵的名字以及可选的偏移坐标,如下代码:
$icons : sprite-map(“icosn/*.png”) ; .next { background : sprite($icons , arrow) no-repeat ; } .add-button { background : sprite($icons , box-add) no-repeat ; }
(2)设置精灵的位置
为了移除重复的背景图片,你可以用sprite-position辅助器或sprite-background-position混合器取代sprite辅助器。
$icons : sprite-map(“icons/*.png”) ; .sprite-base { background : $icons no-repeat ; } .next { @extend .sprite-base ; background-position : sprite-position($icons , arrow) ; } .add-button { @extend .sprite-base ; @include sprite-background-position($icons , box-add); }
sprite-position辅助器和sprite-background-position混合器都做了相同的工作,编译出来的CSS如下:
.sprite-base , .next , .add-button { background : url(‘/images/icons-s943de15a54.png’) } .next { background-position : 0 -70px ; } .add-button { background-position : 0 -358px ; }
(3)设置精灵的尺寸
为包含精灵的尺寸信息,你可以使用prite-dimensions混合器,它需要精灵地图和精灵的名字,并输出经过测量的尺寸。
sprite-dimensions混合器:
$icons : sprite-map(“icons/*.png”) ; .sprite-base { background : $icons no-repeat ; } .next { @extend .sprite-base ; @include sprite-background-position($icons , arrow) ; @include sprite-dimensions($icons , arrow) ; }
这个辅助器会测量精灵并在生成的CSS中写明其宽和高的属性。
sprite-dimensions混合器输出的CSS
.sprite-base , .next{ background : url(‘/images/icons-s943de15154.png’) no-repeat ; } .next { background-position : 0 -70px ; height : 32px ; width : 32px ; }