使用Compass制作Sprite精灵地图

日期:2015-07-09 10:48:45

 在早期,CSS精灵是很简单的。设计师们会把按钮的不同状态做成图片,并把它们做成一张单个图片,然后,在CSS里,他们会设置按钮的宽、高以及背景图片的属性,并在不同的状态下改变背景图的位置。如下图:

1436964736117366.png

 手动处理是一种折磨

我们并没有骗你。如果你不得不手动创建并维护很大的精灵地图及其对应的样式表,你可能会疯掉。好吧,也许这有一点极端了,但至少是在给你自己增加负担。

确实,精灵图片能够明显提升网站的加载时间,但是每改变一张图片,你就不得不更新这张精灵地图。如果需要改变图片的尺寸,你就必须移动周围的图片,并引发其他一系列图片位置的改变,你需要重新测量每张图片,再将其更新到你的样式表中。很明显这是Web设计师和开发者们想象得到的非常枯燥的工作。

事情可以变得更简单一点吗?在网上简单搜索一下,你就可以找到大量的精灵工具,从命令行到基于浏览器的应用应有尽有。每个工具都提供了不同的功能和不同程度的自动化。其中有些工具是很不错的,但是有一个薄弱环节:和工作流程的集成。在这方面,Compass的方案有着独特的优势。

Compass的方案

Compass有一个配置文件用来说明网站图片所在的位置,因为Compass会生成你的CSS,所以它是自动化处理精灵的理想搭档。

Compass生成CSS精灵的过程如下:

(1) 让Compass指向一个精灵的文件夹;
(2) 告诉Compass撰写你的精灵CSS;
(3) 编译你的样式表。

通过两行Sass,你就可以告诉Compass根据一个目录下的每张图片生成精灵,测量它们的尺寸,通过每个图片的文件名撰写出不同类名下的背景位置。当你改变图片时,Compass会自动更新你的样式表,生成一个新的精灵并在必要的情况下更新背景位置。这几乎就是魔术啊!

用Compass 制作精灵

 首先,我们需准备把我们要合成的小图标放在Compass项目的images文件夹里存放图标目录内,如下图:

1436964739252515.jpg

我们使用PNG格式,因为目前的Compass只生成PNG精灵文件。这没什么大不了的,因为PNG是最理想的精灵格式。现在让我们来看一看它会生成怎样的精灵地图。

创建一个精灵地图

 为了将文件夹内的图片转为一张精灵地图,我们需要在sass目录下创建一个_sprites.scss文件,这个文件主要就是用来存放生成精灵图需要的代码,这样做是为了方便管理项目。

1436964739127151.jpg

生成精灵的CSS

Compass有两个很顺手的混合器,可以为你自动生成精灵的CSS:

@include all-<map>-sprites;
@include <map>-sprite($name);

这里的<map>是一个占位符,它会被替换为包含精灵图片的文件夹的名称。在本例中,它就是icons。all-sprites混合器会为整个精灵地图撰写所有必要的CSS。而第二个混合器将会输出一个独立命名精灵的CSS。这两个混合器都会随着精灵的导入而创建,因此它们只能在导入之后使用。

all-sprites混合器

下面看看我们_sprites.scss文件里的代码:

//sass style
@import "compass/utilities/sprites"; //导入sprites模块
@import "icons/*.png"; //导入icons文件夹内后缀名为PNG所有图片,创建基础类icons-sprite,同时在images文件夹可以看到生成的精灵图
@include all-icons-sprites; //混合器生成精灵图代码

这个all-icons-sprites混合器将会为精灵地图中的每个精灵撰写必要的CSS。

接着看看生成的CSS:

.icons-sprite, .icons-facebook, .icons-flickr, ... {
  background-image: url('/images/icons-sde05ca21e7.png');
  background-repeat: no-repeat;
}
.icons-facebook {  background-position: 0 0;}
.icons-flickr {  background-position: 0 -32px;}
...

注意:到这一步时我们发现引用的精灵图片并不会显示,在浏览器查看一下图片发现是图片路径出问题了,这可怎么办呢?

很简单,只需要打开Compass的配置文件config.rb配置一下参数就行了,打开配置文件找到:

# relative_assets = true

接着把前面的#去掉,激活这个参数。然后重启一下监听器(compass watch),看看是不是路径已经正确啦。

为了节省空间,我们简化了前面的CSS输出,实际上它会生成几十行代码。。现在让我们看看这个混合器都生成了什么:

(1) 它为设置所有来自images/icons/的精灵样式创建了一个基础类icons-sprite;
(2) 它为其精灵目录下的每一个文件名创建了类;
(3) 它为所有的精灵都增加了背景图片;
(4) 它为所有的精灵都增加了背景位置。

默认情况下,Compass不会设置这些元素的宽和高。Compass可以自动生成精灵的尺寸,但我们不一定总需要它。

如果你决定创建不止一个精灵地图,可以添加图片到另一个目录,然后导入它们,再使用all-sprites混合器,这样就大功告成了。

single-sprite混合器

这个混合器将会针对单个的精灵输出CSS。

//sass style
@import "compass/utilities/sprites";
@import "icons/*.png";
.add-button {
  @include icons-sprite(twitter);
}

生成single-sprite的CSS:

.icons-sprite, .add-button {
  background-image: url('../images/icons-sde05ca21e7.png');
  background-repeat: no-repeat;
}
.add-button {
  background-position: 0 -320px;
}

有了single-sprite混合器,就没有必要生成一个类名了,因为样式已经包含在了选择器里。当Compass添加background-image和background-position样式时,会直接使用这些选择器,在这个例子里是.add-button。相比简单方便的all-sprites混合器,这个方式生成更少的CSS,也让你对输出有更多的控制。

这是一个好的开始,但有时你还需要对精灵的过程进行更多的控制。接下来,你将会看到Compass如何让你不费吹灰之力完成更多的控制。

配置Compass 精灵

Compass使用包含导入图片的文件夹的名称来命名这些配置变量、混合器和函数。在前面的例子中,你从一个名叫&ldquo;icons&rdquo;的文件夹导入了精灵,而这正是all-icons-sprites混合器名字的来源。如果你从嵌套文件夹导入了精灵,那么Compass会使用最末端的包含精灵的文件夹名。所以@import "sprites/social/*.png";会将&ldquo;social&rdquo;用于其变量、混合器和函数的名称中。如此一来,即使使用多个精灵地图也不会产生命名冲突。

自定义精灵地图

你可以自定义一个精灵地图或通过其配置变量有针对性地定义精灵。影响整个精灵地图的变量的名称以地图名称开头,而仅改变单个精灵的变量的名称是地图名紧跟精灵文件名。

变量命名表

$<map>-<property>: setting;
$<map>-<sprite>-<property>: setting;

在我们的示例项目中,精灵文件夹的名称是&ldquo;icons&rdquo;,所以改变间距的变量被命名为$icons-spacing 。而为了设置icons/twitter.png 间距变量, 你应该赋值给$icons-twitter-spacing。

记住, 这些变量必须在导入精灵之前被定义, 否则不会生效。

配置精灵间距

Compass允许你通过配置精灵间距变量改变精灵的间距:

$<map>-spacing: 0px;
$<map>-<sprite>-spacing: 0px;

默认值是0px,这意味着每个精灵被拼入精灵地图时不带任何间距。设置这个变量或单独给每个精灵赋值,会使得每个精灵在拼合时在周围增加若干像素的透明间距。

$icons-spacing: 5px;
$icons-twitter-spacing: 15px;

配置前后精灵图对照:

1436964740107755.jpg

当小精灵被用在大尺寸元素的背景中时,间距是格外有用的。如果没有间距,小精灵边上的其他精灵可能就会露出来。

设置精灵的重复性

在一些情况下,精灵地图中水平方向的重复精灵会有大用处。为此,你可以设置精灵的重复性变量:

$<map>-repeat: no-repeat/repeat-x;
$<map>-<sprite>-repeat: no-repeat/repeat-x;

其默认值是no-repeat,但是你可以将其改为repeat-x使其在整个x轴平铺。这一设置可以用在整个精灵地图上,也可以用在某个单独的精灵上。

下面让facebook图标横向平铺:

$icons-facebook-repeat: repeat-x;

1436964740857238.png

这导致箭头图标横向平铺整个图片。重复的箭头图标横跨整个精灵地图和最宽的compass的logo对齐。Compass发布时还不支持跨y轴的图片重复。

设置精灵的位置

有的时候,移动一个精灵的位置是非常有帮助的。Compass允许你通过设置位置变量来横向移动图片:

$<map>-position: 0px;
$<map>-<sprite>-position: 0px;

这个变量调整了精灵地图中精灵的横向位置。其默认值为0px,意味着每个精灵都是左对齐的。这个值可以是百分比,也可以是像素值。

接下来设置精灵图和facebook图标的位置:

$icons-position: 5px;
$icons-facebook-position: 100%;

1436964739529174.png

 设置精灵地图的布局

Compass有以下几种精灵的布局可供选择:

$<map>-layout: vertical/horizontal/diagonal/smart;
vertical:垂直布局;
horizontal:横向布局;
diagonal:对角线布局;
smart:智能布局。

默认的布局是vertical,从整体上影响精灵地图布局,告知Compass如何排布所有的精灵。大多数情况下,你可能需要将布局设置为smart,这种布局会让Compass产生最小的空白区域。

$icons-layout: smart;

 1436964740849623.png

位置和重复性的设置只会应用到横向或纵向布局的精灵地图中。对于采用智能布局或对角线布局的精灵地图,位置和重复性的设置是无效的。

清除过期的精灵地图

当添加、删除或改变图片后,会生成新的精灵地图。Compass会自动为你移除旧的精灵地图,或者你也可以把它们保留下来:

$<map>-clean-up: true/false;

默认情况下,当生成新的精灵地图时,Compass会自动把旧的移除。这会避免你的硬盘被不再使用的文件填满,同时也确保你不会困惑自己的样式表到底在使用哪个文件。如果你喜欢手动移除旧的精灵地图,你也可以将其设置为false。

到此为止,我们知道了如何修改Compass生成精灵地图。接下来,我们看看如何自定义Compass生成的CSS代码。

自定义精灵的CSS

你已经知道Compass在精灵地图中布置图片是多么方便。尽管这些精灵地图的改变必然会影响Compass最终生成的CSS,这里还是有一些办法让你直接自定义生成的CSS。

输出精灵的尺寸

如果你想要给一个特殊的精灵设置尺寸,你可以使用精灵尺寸的辅助器:

<map>-sprite-height($name)
<map>-sprite-width($name)

这里有两个函数可以让Compass测量原始精灵的尺寸并将其输出以便你在样式表里使用它。通过使用这些辅助器函数, 你可以设置单个精灵的宽和高。

下面来获取compass-logo的宽和高:

@import "icons/*.png";
.compass-logo {
  @include icons-sprite(compass-logo);
  width: icons-sprite-width(compass-logo);
  height: icons-sprite-height(compass-logo);
}

生成的CSS:

.icons-sprite, .compass-logo {
  background-image: url('../images/icons-s990e911b07.png');
  background-repeat: no-repeat;
}
.compass-logo {
  background-position: 0 0;
  width: 423px;
  height: 176px;
}

另外,如果你想要为精灵地图中的每个精灵自动设置尺寸,你可以为这个精灵地图设置一个配置变量。

$<map>-sprite-dimensions: true/false;

默认值是false,将其设置为true会测量每张精灵图片并为其精灵类的宽和高赋值。

$icons-sprite-dimensions: ture;
@import "icons/*.png";
.compass-logo {
  @include icons-sprite(compass-logo);
}

生成的代码:

.icons-sprite, .compass-logo {
  background-image: url('../images/icons-s990e911b07.png');
  background-repeat: no-repeat;
}
.compass-logo {
  background-position: 0 0;
  height: 176px;
  width: 423px;
}

相比起手动设置精灵的尺寸,自动生成它们是如此美好。不过如果所有的图标都是相同的尺寸,那么为每一个精灵注明尺寸会让CSS显得臃肿。为此,我们可以为精灵地图的基础类手动设置尺寸。 

精灵的基础类

Compass可以方便地通过生成一个基础类为每个精灵应用普通样式。你可以设置基础类变量来选择你的所属类名称:

$<map>-sprite-base-class: ".class-name";

当你使用全部精灵或单独精灵的混合器时,Compass会输出一个精灵的基础类,并且其选择器还会串联所有设置了background-image属性的选择器。每个精灵地图的基础类都以其文件夹的名字命名。如果精灵文件夹的名字是&ldquo;icons&rdquo;,则精灵地图的基础类就是.icons-sprites。

让我们看看你会如何改变它:

$icons-sprite-base-class: ".pub-base";
@import "icons/*.png";
.compass-logo {
  @include icons-sprite(compass-logo);
}

生成的CSS:

.pub-base, .compass-logo {
  background-image: url('../images/icons-s990e911b07.png');
  background-repeat: no-repeat;
}
.compass-logo {
  background-position: 0 0;
}

每个精灵类都扩展了基础类。所以你添加到基础类的任何样式都会影响你的每一个精灵。

记住,输出的CSS中仅有基础类发生改变。变量名、函数和混合器依然是相同的,它们的名字源于精灵地图的文件夹。

魔术精灵选择器

Compass可以通过伪选择器自动生成精灵的CSS,但是如果需要的话,你可以禁用它:

$disable-magic-sprite-selectors: true/false;

魔术精灵选择器是默认开启的,也就是说Compass在精灵时会根据以&ldquo;_hover&rdquo;&ldquo;_active&rdquo;或_target结尾的名字自动输出CSS的:hover、:active和:target伪选择器。

例如,如果你想要为正常和悬停状态设置不同的精灵,那么就在你的精灵文件夹里加入twitter.png和twitter_hover.png,Compass就会为悬停的伪类生成CSS精灵的背景。

.twitter {
  background-position: 0 -528px;
}
.twitter:hover, .twitter.twitter-hover {
  background-position: 0 -496px;
}

如果魔术伪选择器和你选择的图片命名表冲突,请设置为true从而对所有精灵地图禁用这个功能。 

驾驭精灵辅助器

至此,我们已经看过了自动生成精灵地图和CSS的工具,以及一些自定义输出的选项。在多数情况下,这些魔术般的混合器可以满足你的所有需求。但是你偶尔也需要抛开这些东西亲自动手。

为了达到生成精灵的目的,Compass依仗了一些辅助器函数。通过对其深入了解,在制作精灵时你会有更大的把握和施展空间。

创建精灵地图

如你早些时候看到的,创建一个特定输入的精灵地图,如@import "icons/*.png";,并不仅仅是创建了一个精灵地图;它还为精灵地图和每个精灵设置了混合器和变量。如果你使用精灵辅助器,就不必使用这些变量和混合器,否则会造成精灵导入的大材小用。取而代之的是sprite-map辅助器。

sprite-map($glob, ...);

这个辅助器接收了一组类似"icons/*.png"的图片,以及设置精灵地图或单独精灵的可选关键字参数。这里有几个例子:

sprite-map辅助器

$icons: sprite-map("icons/*.png", $layout: smart);

它会创建一个智能布局的精灵地图,并把精灵地图的图片URL赋值给$icons变量。我们稍后会在其他的辅助器里用这个变量生成CSS。

sprite-map辅助器&mdash;&mdash;设置一个单独的精灵

$icons: sprite-map("icons/*.png", $twitter-spacing: 5px);

任何精灵地图或单独精灵的属性都可以配置,仅使用我们早些时候提到的去掉<map>命名空间的配置变量。你可以使用$repeat 替代$<map>-repeat 的重复性配置; 也可以使用$twitter-repeat替代$<map>-<sprite>-repeat,这里的&ldquo;twitter&rdquo;是你配置的精灵的名称。

撰写精灵的CSS 

在Compass为你生成精灵地图之后,你仍然需要写出每个精灵的CSS。为此,我们将转向一些其他的辅助器和混合器。

sprite辅助器

sprite辅助器使得撰写精灵的CSS非常简单:

sprite($map, $sprite, [$offset-x], [$offset-y]);

sprite辅助器需要精灵地图、精灵的名字以及可选的偏移坐标。

$icons: sprite-map("icons/*.png");
.twitter {
  background: sprite($icons, twitter) no-repeat;
}

 编译后的CSS:

.twitter {
  background: url('../images/icons-saf8ea9b2cd.png') 0 -496px no-repeat;
}

这仅仅会输出背景属性,而不会成为一个精灵的基础类或其他任何你不需要的CSS,精灵基础类的一个优点是你只需赋值一次背景图片;在这里它会赋值给每一个类,而这是不必要的重复。 

设置精灵的位置

为了移除重复的背景图片,你可以用sprite-position辅助器或sprite-background-position混合器取代sprite辅助器。

sprite-position($map, $sprite, [$offset-x], [$offset-y]) 
sprite-background-position($map, $sprite, [$offset-x], [$offset-y])

这里的辅助器和混合器都需要一个精灵地图、精灵的名称以及可选的位置偏移量。

$icons: sprite-map("icons/*.png");
.sprite-base {
  background: $icons no-repeat;
}
.twitter {
  @extend .sprite-base;
  background-position: sprite-position($icons, twitter);
}
.facebook {
  @extend .sprite-base;
  @include sprite-background-position($icons, facebook);
}

编译后的CSS:

.sprite-base, .twitter, .facebook {
  background: url('../images/icons-saf8ea9b2cd.png') no-repeat;
}
.twitter {
  background-position: 0 -496px;
}
.facebook {
  background-position: 0 -176px;
}

sprite-position辅助器和sprite-background-position混合器都做了相同的工作,至于用哪个是个人偏好问题。

在这里你可以看到CSS是如此简单。你有更大的灵活度,且不必重复。不过最好能再加入精灵的尺寸。

设置精灵的尺寸

为包含精灵的尺寸信息,你可以使用sprite-dimensions混合器,它需要精灵地图和精灵的名字,并输出经过测量的尺寸。

$icons: sprite-map("icons/*.png");
.sprite-base {
  background: $icons no-repeat;
}
.twitter {
  @extend .sprite-base;
  background-position: sprite-position($icons, twitter);
  @include sprite-dimensions($icons, twitter);
}

编译后的CSS:

.sprite-base, .twitter {
  background: url('../images/icons-saf8ea9b2cd.png') no-repeat;
}
.twitter {
  background-position: 0 -496px;
  height: 32px;
  width: 32px;
}

这个辅助器会测量精灵并在生成的CSS中写明其宽和高的属性。 以上就是所有的内容了。有了这些功能和灵活性,你应该不再担心在Web设计项目中加入精灵了吧。