CSS Sprite图片处理技巧

所属分类: 网页制作 / CSS 阅读数: 1517
收藏 0 赞 0 分享

  在以前我们的工作中,以传统切图思想进行操作,讲究精细,图片规格越小越好,重量越小越好,其实规格大小无所谓,计算机统一都按Byte计算。
  客户端每显示一张图片都会向服务器发送请求,所以,图片越多请求次数越多,造成延迟的可能性也就越大。因为一张图片的传输时间,通常远小于请求等待的时间。
  典型如文本编辑器,小图标特别多,打开时一张张跑出来,给用户的感觉很不好。如果能用一张图解决,则不会有这个问题,比如百度空间、163博客、Gmail都是这么做的,jb51.net也提倡这样的操作方法。

CSS Sprites: Image Slicing’s Kiss of Death
Back when video games were still fun (we’re talking about the 8-bit glory days here), graphics were a much simpler matter by necessity. Bitmapped 2-dimensional character data and background scenery was individually drawn, much like today’s resurgent pixel art. Hundreds and later thousands of small graphics called sprites were the building blocks for all things visual in a game.
example sprites
As game complexity increased, techniques developed to manage the multitude of sprites while keeping game play flowing. One variation saw sprites being plugged into a master grid, then later pulled out as needed by code that mapped positions of each individual graphic, and selectively painted them on the screen.

And what does this have to do with the web?
Everything old is new again, and though the rise of 3D games has made sprite maps obsolete, the concurrent rise of mobile devices with 2D gaming capabilities have brought them back into vogue. And now, with a bit of math and a lot of CSS, we’re going to take the basic concept and apply it to the world of web design.
Specifically, we’re going to replace old-school image slicing and dicing (and the necessary JavaScript) with a CSS solution. And because of the way CSS works, we’re going to take it further: by building a grid of images and devising a way to get each individual cell out of the grid, we can store all buttons/navigation items/whatever we wish in a single master image file, along with the associated “before” and “after” link states.

How do CSS Sprites work?
As it turns out, the basic tools to do this are built into CSS, given a bit of creative thinking.
Let’s start with the master image itself. Dividing a rectangle into four items, you’ll observe in this master image that our intended “before" link images are on the top row, with “after" :hover states immediately below. There’s no clear division between the four links at the moment, so imagine that each piece of text is a link for now. (For the sake of simplicity, we’ll continue to refer to link images as “before” images and the :hover state as “after” for the rest of this article. It’s possible to extend this method to :active, :focus, and :visited links states as well, but we won’t go into that here.)
Those familiar with Petr Stanicek’s (Pixy) Fast Rollovers may already see where we’re going with this. This article owes a debt of gratitude to Pixy’s example for the basic function we’ll be relying on. But let’s not get ahead of ourselves.
On to the HTML. Every good CSS trick strives to add a layer of visuals on top of a clean block of code, and this technique is no exception:
<ul id="skyline"> <li id="panel1b"><a href="#1"></a></li> <li id="panel2b"><a href="#2"></a></li> <li id="panel3b"><a href="#3"></a></li> <li id="panel4b"><a href="#4"></a></li> </ul>
This code will serve as a base for our example. Light-weight, simple markup that degrades well in older and CSS-disabled browsers is all the rage, and it’s a trend that’s good for the industry. It’s a great ideal to shoot for. (We’ll ignore any text inside the links for the time being. Apply your favorite image replacement technique later to hide the text you’ll end up adding.)

Applying the CSS
With those basic building blocks, it’s time to build the CSS. A quick note before we start — because of an IE glitch, we’ll be tiling the after image on top of the before image when we need it, instead of replacing one with the other. The result makes no real visual difference if we line them up precisely, but this method avoids what otherwise would be an obvious “flicker” effect that we don’t want.
#skyline { width: 400px; height: 200px; background: url(test-3.jpg); margin: 10px auto; padding: 0; position: relative;} #skyline li { margin: 0; padding: 0; list-style: none; position: absolute; top: 0;} #skyline li, #skyline a { height: 200px; display: block;}
Counter-intuitively, we’re not assigning the before image to the links at all, it’s applied to the <ul> instead. You’ll see why in a moment.
The rest of the CSS in the above example sets things like the dimensions of the #skyline block and the list items, starting positions for the list items, and it turns off the unwanted list bullets.
We’ll be leaving the links themselves as empty, transparent blocks (though with specific dimensions) to trigger the link activity, and position them using the containing <li>s. If we were to position the links themselves and effectively ignore the <li>s, we’d start seeing errors in older browsers, so let’s avoid this.

Hovers
In the past we would have applied some JavaScript to swap in a new image for the after state. Instead our after states are in one image, so all we need is a way to selectively pull each state out for the appropriate link.
If we apply the master image to the :hover state without additional values, we make only the top left corner visible — not what we want, though clipped by the link area, which is what we want. We need to move the position of the image somehow.
We’re dealing with known pixel values; a little bit of math should enable us to offset that background image enough both vertically and horizontally so that only the piece containing the after state shows.
That’s exactly what we’ll do:
#panel1b a:hover { background: transparent url(test-3.jpg) 0 -200px no-repeat;} #panel2b a:hover { background: transparent url(test-3.jpg) -96px -200px no-repeat;} #panel3b a:hover { background: transparent url(test-3.jpg) -172px -200px no-repeat;} #panel4b a:hover { background: transparent url(test-3.jpg) -283px -200px no-repeat;}
Where did we get those pixel values? Let’s break it down: the first value is of course the horizontal offset (from the left edge), and the second is the vertical.
Each vertical value is equal; since the master image is 400 pixels high and the after states sit in the bottom half, we’ve simply divided the height. Shifting the whole background image up by 200px requires us to apply the value as a negative number. Think of the top edge of the link as the starting point, or 0. To position the background image 200 pixels above this point, it makes sense to move the starting point -200px.
Likewise, if the left edge of each link is effectively 0, we’ll need to offset the background image horizontally by the width of all <li>s prior to the one we’re working with. So the first link doesn’t require an offset, since there are no pixels before its horizontal starting point. The second link requires an offset the width of the first, the third link requires an offset of the combined width of the first two links, and the last requires an offset of the combined width of all three previous links.
It’s a bit cumbersome to explain the process, but playing around with the values will quickly show you how the offsets work, and once you’re familiar it’s not all that hard to do.
So there you have it. Single-image CSS rollovers, degradable to a simple unordered list.

Buttons
There’s no reason why we have to leave the links touching each other, side-by-side as they were in the previous example. Image maps may be convenient in some spots, but what about separating each link into its own stand-alone button? That way we can add borders and margins, let the underlying background show through, and generally treat them as separately as we need to.
In fact, the building blocks are already in place. We really don’t need to modify our code too radically; the main change is in creating a new background image that doesn’t continue from link to link like the last example did. Since we can’t rely on the <ul> for placing the original background image, we’ll end up applying it to all <li>s instead and offsetting each the same way we offset the after states in the prior example.
With an appropriate image and a bit of spacing between each <li>, we’ve got buttons.
Note that in this example we’ve added 1px borders which, of course, count toward the final width of the links. This affects our offset values; we’ve compensated by adding 2px to the offsets where appropriate.

Irregular shapes
Up till now we’ve focused only on rectangular, non-overlapping shapes. What about the more complex image maps that image slicers like Fireworks and ImageReady export so easily? Relax, we’ve got you covered there too.
We’ll start the same way as the first example, by applying the background image to the <ul> and turning off list item bullets and setting widths and so forth. The big difference is where we position the <li>s; the goal is to surround each graphical element with a box that tightly hugs the edges.
Again, because of the ability to use absolute positioning relative to the top left corner of the <ul>, we’re able to precisely place our links exactly where we want them. Now all that’s left is to set up the hover states.
Worth noting is that in this case, a single set of before and after images wasn’t enough. Because of the overlapping objects, relying on only one after state would show pieces of surrounding objects’ after states. In fact, it would show precisely the pieces that fall within the link’s borders. (Easiest to just see it in action.)
How to avoid this? By adding a second after state, and carefully selecting which objects go where. The master image in this case has split the purple and blue objects into the first after state, and the green, orange and yellow objects into the second. This order allows boxes to be drawn around each object’s after state without including pieces of the surrounding objects. And the illusion is complete.

Benefits and pitfalls
A couple of final thoughts. Our new CSS Sprite method tests well in most modern browsers. The notable exception is Opera 6, which doesn’t apply a background image on link hover states. Why, we’re not sure, but it means that our hovers don’t work. The links still do, and if they’ve been labeled properly, the net result will be a static, but usable image map in Opera 6. We’re willing to live with that, especially now that Opera 7 has been around for a while.
The other concern is familiar to anyone who has spent time with FIR. In the rare cases in which users have turned off images in their browsers but retained CSS, a big empty hole will appear in the page where we expect our images to be placed. The links are still there and clickable, but nothing visually appears. At press time, there was no known way around this.
Then there’s file size. The natural tendency is to assume that a full double-sized image must be heavier than a similar set of sliced images, since the overall image area will usually be larger. All image formats have a certain amount of overhead though (which is why a 1px by 1px white GIF saves to around 50 bytes), and the more slices you have, the more quickly that overhead adds up. Plus, one master image requires only a single color table when using a GIF, but each slice would need its own. Preliminary tests suggest that all this indicates smaller total file sizes for CSS Sprites, or at the very least not appreciably larger sizes.
And lastly, let’s not forget that our markup is nice and clean, with all the advantages that go along with that. HTML lists degrade wonderfully, and a proper image replacement technique will leave the text links accessible to screenreaders. Replacing the sprite imagery is dead simple, since all of our dimensions and offsets are controlled in a single CSS file, and all of our imagery sits in a single image.
原文连接:http://www.alistapart.com/articles/sprites/

更多精彩内容其他人还在看

CSS配合JavaScript做酷的动态页面效果

  利用CSS配合JavaScript的可以做很多更酷的动态页面效果,在本教程的最后给大家简单介绍一下CSS配合JS的应用。首先,要搞清楚事件和动作的概念。在客户端脚本中,JavaScript 通过对事件进行响应来获得与用户的交互。例如,当用户单击一个按钮或者在某段文字上移动鼠标
收藏 0 赞 0 分享

WEB标准,Web前端开发工程师必备技术列表

  想要打造并拥有一流的Web产品开发团队,在团队成员基础能力上一定要下功夫。对于Web前端产品开发来说,仅仅掌握Web1.0时代简单的"网页套接"是完全不够的。我结合自己的团队配备,特此罗列了Web前端产品工程师所涉及的技能列表如下:   通过许多实际项目,
收藏 0 赞 0 分享

用CSS制作Alpha滤镜测试板

alpha滤镜给制作网页特效提供了较大的创作空间,但由于它控制参数较多,在实际应用时,为了确定一组合适的参数值,不得不反复调整修改,在编辑窗口和预览窗口来回倒腾,甚是麻烦,本文介绍了一种简单的方法。制作一个“Alpha滤镜参数测试板”,在测试板上输入参数
收藏 0 赞 0 分享

非常流行的所谓的气泡窗口

普通的Alt无法自定义风格,而Sweet Titles通过JS脚本与CSS的集合.自定义了这种伪Alt风格. 前一段时间非常流行的,就所谓的气泡窗口(鼠标移到链接处出现的). 我们这里实现的用的是Sweet Titles的插件.显示效果完全由CSS控制.. 先下载Sweet Ti
收藏 0 赞 0 分享

CSS教程:li和ul标签用法举例

LI代码的格式化: A).运用CSS格式化列表符: ul li{ list-style-type:none; } B).如果你想将列表符换成图像,则: ul li{ list-style-type:none; list-style-image: url(/blog/images/
收藏 0 赞 0 分享

CSS教程:CSS中的定位(position)

  使用CSS来定位页面内层的位置,一直是比较难以掌握的事情,很多时候,往往被绝对定位的元素,总是以浏览器的左上角为坐标原点,此时,如果浏览器的大小改变,被定义的层就会偏离设计想要的位置,让人很挠头。   其实,要想控制好层的绝对定位,只要理解CSS中关于定位
收藏 0 赞 0 分享

CSS教程:盒模型(BOX Model)

  如果想熟练掌握DIV和CSS的布局方法,首先要对盒模型有足够的了解。每个HTML元素都可以看作一个装了东西的盒子,盒子里面的内容到盒子的边框之间的距离即填充(padding),盒子本身有边框(border),而盒子边框外和其他盒子之间,还有边界(margin),如图1所示。
收藏 0 赞 0 分享

无延迟翻滚的图形与CSS混合风格按钮

  在一个具有图形背景的按钮中添加CSS风格的文本,这种建立按钮的方法结合了具有CSS翻滚(CSS rollover)标记的开发速度和效率,从而有效地提高按钮外表图像的三维效果。   相比于常规的图形按钮,这些图形/CSS混合按钮可易于建立和载入,因为你只需要为空白按钮外面
收藏 0 赞 0 分享

css里expression实现界面对象的批量控制

用过css样式我们就知道, 可以定义一批对象的class属性来指定同一个样式来统一界面. 但如何统一同类型的对象的事件? 比如:界面有无数个 <img src="**.jpg"> 如何实现鼠标经过此图片, 图片的src变成是**_over.jpg?
收藏 0 赞 0 分享

CSS教程:水平对齐(text-align)

  水平对齐(text-align),用以设定元素内文本的水平对齐方式。   1.语法   text-align具体参数如下: 语法:text-align:left|right|center|justify 说明:设定元素内文本的水平对齐方式。 参数:left:左
收藏 0 赞 0 分享
查看更多