Skip navigation
Help

Sprite

warning: Creating default object from empty value in /var/www/vhosts/sayforward.com/subdomains/recorder/httpdocs/modules/taxonomy/taxonomy.pages.inc on line 33.

Can computers learn to be creative? My experiments applying machine learning to games.

0
Your rating: None

  

I’m pretty confident that I won’t surprise anyone here by saying that CSS sprites have been around for quite a while now, rearing their somewhat controversial heads in the Web development sphere as early as 2003.

Still, the CSS sprite hasn’t truly found its way into the everyday toolkit of the common Web developer. While the theory behind CSS sprites is easy enough and its advantages are clear, they still prove to be too bothersome to implement, especially when time is short and deadlines are looming. Barriers exist to be breached, though, and we’re not going to let a couple of tiny bumps in the road spoil the greater perks of the CSS sprite.

If you want more background information on best practices and practical use cases, definitely read “The Mystery of CSS Sprites: Techniques, Tools and Resources.” If you’re the defensive type, I would recommend “CSS Sprites: Useful Technique, or Potential Nuisance?,” which discusses possible caveats.

I won’t take a stance on the validity of CSS sprites. The aim of this article is to find out why people still find it difficult to use CSS sprites. Also, we’ll come up with a couple of substantial improvements to current techniques. So, start up Photoshop (or your CSS sprite tool of choice), put on your LESS and Sass hats, and brush up your CSS pseudo-element skills, because we’ll be mixing and matching our way to easier CSS sprite implementation.

The Problem With CSS Sprites

While Photoshop is booting, take a moment to consider why CSS sprites have had such a hard time getting widespread acceptance and support. I’m always struggling to find the correct starting position for each image within a sprite. I’ll usually forget the exact coordinates by the time I need to write them down in the style sheet, especially when the image is located at x:259, y:182 and measures 17×13 pixels.

I’m always switching back and forth between Photoshop and my CSS editor to write down the correct values, getting more and more frustrated with every switch. I know software is out there specifically tailored to help us deal with this, but I’ve never found an application that lets me properly structure its CSS output so that I can just copy and paste it into my CSS file.

Another important thing to realize is that CSS sprites are meant to be one part of our website optimization toolkit. Many of the people who write and blog about CSS sprites are comfortably wearing their optimization hats while laying out best practices, often going a little overboard and losing track of how much effort it requires to implement their methods of choice.

This is fine if you’re working on an optimization project, but it becomes counterproductive when you need to build a website from scratch while fighting tight deadlines. If you have time to truly focus on implementing a CSS sprite, it’s really not all that hard; but if you have to juggle 50 other priorities at the same time, it does turn into a nuisance for many developers. With these two factors in mind, we’ll try to find a way to make image targeting easier, while coming to terms with the fact that sometimes we have to sacrifice full optimization in the name of ease of development.

 Amazon, Google and Facebook.
CSS sprites in the wild: Amazon, Google and Facebook.

Preparing The Sprite

If you look online for examples of CSS sprites, you’ll see that most are optimized for an ideal use of real estate—gaps between images are kept to a minimum in order to keep the load of the entire sprite as low as possible. This reduces loading time considerably when the image is first downloaded, but it also introduces those horrible image coordinates that we mentioned earlier. So, why not take a slightly different approach? Let’s look for an easier way to target images while making sure the resulting sprite is not substantially bigger than the sum of its individual images.

Rather than try to stack the images in such a way that makes the resulting sprite as small as possible, let’s try a different layout. Instead of a random grid, we’re going to build a nice square grid, reserving the space of each square for one image (although larger images might cover multiple squares). The goal is to be able to target the starting point of every image (top-left corner) with a very simple mathematical function.

The size of the grid squares will depend on the average dimension of the images that you’ll be spriting. For my website, I used a 32×32 pixel grid (because only one image exceeds this dimension), but grid sizes will vary according to the situation. Another thing to take into account is the image bleeding that can occur when zooming a page; if you want to play it safe, add a little padding to each image within the sprite. For extra optimization, you could also use a rectangular grid instead of a square grid, further reducing any wasted space; while a tad more complex, this isn’t much different from what we’ll be doing. For this article, though, we’ll stick with the square grid.

Preparing The Sprite: A Photoshop Bonus

I’m no designer, so I’m not sure how applicable this section is beyond the realm of Photoshop, but there are still some noteworthy improvements that can be made before we get to the actual code. First of all, visualizing the grid can be of great help. Photoshop has guides to do this (so you don’t actually have to include the markers in your sprite), with the added bonus that layers will snap to these guides (making pixel-perfect positioning of each individual image much easier).

Manually adding these guides can be somewhat of a drag, though. Luckily, a colleague of mine (hats off to Filip Van Tendeloo) was kind enough to write and share a little Photoshop script that builds this grid of guides automatically based on the base size of your square. Pretty convenient, no? Just download the script, save it in the Presets\Scripts directory, and choose File → Scripts → Sprite Grid from the Photoshop menu.

Finally, to really finish things off, you can add numbers to the x and y axes of your grid so that you can easily pinpoint every square in the grid. Don’t add these numbers to the actual sprite, though; just copy the sprite into a new image and add them there. These numbers are just for reference—but trust me, they will definitely come in handy in a minute.

Example of a reference image.
Example of a reference image.

If you can’t (or don’t want to) use preprocessing languages such as LESS and Sass, just add the coordinates of each square instead.

LESS And Sass To The Rescue

With all of the images on the same square grid, we can now easily compute the top-left coordinate of each image (this coordinate is the exact match needed for the background-position values to reposition the sprite). Just take the base size of the grid and multiply it by the numbers that you just added to your reference image. Say you need to target the image at a position of (5,3), and your grid size is 32 pixels; the top-left position of your image will be 32 × (5,3) = (160,96). To add these values to your CSS file, just use their negative equivalents, like so:

background-position: -160px -96px;

Leave your calculator where it is for the time being, because it would be too much of a hassle. If computers are good at anything, it’s doing calculations, so we’re going to make good use of that power. Plain CSS doesn’t allow us to do calculations (yet), but languages like LESS and Sass were made to do just that. If you need more background information, check out the article “An Introduction to LESS and Comparison to Sass.” While both languages offer similar functionality, their syntaxes are slightly different. I’m a LESS man myself, but if you’re used to Sass, converting the following examples to Sass code shouldn’t be too hard. Now for some advanced CSS magic:

@spriteGrid: 32px;
.sprite(@x, @y) {
   background: url(img/sprite.png) no-repeat;
   background-position: -(@x*@spriteGrid) -(@y*@spriteGrid);
}

Nothing too exciting so far. First, we’ve defined the grid size using a LESS variable (@spriteGrid). Then, we made a mixin that accepts the numbers we added to the reference image earlier. This mixin uses the grid variable and the image’s coordinates to calculate the base position of the image that we want to target. It might not look fancy, but it sure makes the basic use of sprites a lot easier already. From now on, you can just use .sprite(1,5), and that’s all there is to it. No more annoying calculations or finding random start coordinates.

Of course, the mixin above only works in our somewhat simplified example (using a square grid and just one sprite). Some websites out there are more complex and might require different sprites using rectangular grids for additional optimization. This isn’t exactly impossible to fix with LESS, though:

.spriteHelper(@image, @x, @y, @spriteX, @spriteY) {
   background: url("img/@{image}.png") no-repeat;
   background-position: -(@x*@spriteX) -(@y*@spriteY);
}
.sprite(@image, @x, @y) when (@image = sprite1), (@image = sprite3){
   @spriteX: 32px;
   @spriteY: 16px;
   .spriteHelper(@image, @x, @y, @spriteX, @spriteY);
}
.sprite(@image, @x, @y) when (@image = sprite2){
   @spriteX: 64px;
   @spriteY: 32px;
   .spriteHelper(@image, @x, @y, @spriteX, @spriteY);
}

Yes, this looks a bit more daunting, but it’s still pretty basic if you take a minute to understand what’s going on. Most importantly, the added complexity is safely hidden away inside the LESS mixins, and we’re still able to use the same sprite mixin as before, only now with three parameters in total. We’ve just added an image parameter so that we can easily determine which sprite to use each time we call our mixin.

Different sprites might have different grid dimensions, though; so, for each grid dimension, we need to write a separate LESS mixin. We match each sprite to its specific dimension (the example above handles three different sprites and matches it to two different grid dimensions), and we define the dimensions (@spriteX and @spriteY) locally in each mixin. Once that is done, we offload the rest of the work to a little .spriteHelper mixin that does all of the necessary calculations and gives us the same result as before.

The “guards” (as LESS calls them—characterized by the keyword “when”) are quite new to the LESS vocabulary, so do make sure you’re using the latest version of the LESS engine if you attempt to run this yourself. It does offer a great way to keep the sprite mixin as clear and concise as possible, though. Just pass the sprite you want to use to the sprite mixin, and LESS will figure out the rest for you.

Common CSS Sprite Use Cases

With these mixins at our disposal, let’s see what different CSS sprite use cases we can identify and find out whether capturing these use cases in additional LESS mixins is possible. Once again, in order to minimize complexity in the upcoming sections, we’ll assume you’re working with a square grid sprite. If you need a rectangular grid, just add the image’s parameter to the LESS mixins we’ll be working with, and everything should be fine.

For each use case, we’ll define two mixins: one with and one without height and width parameters. If you’re like me and you keep misspelling the height and width keywords, the second mixin might come in handy. It does leave you the responsibility of learning the correct order of the parameters, though. LESS allows you to define these mixins in the same document, however, so there’s really no harm in listing them both, picking whichever is easiest for you.

1. Replaced Text

This is probably the easiest use case, occurring when we have an html element at our disposal that can be given a fixed dimension (in order to ensure we can hide the unwanted parts of the sprite). We’ll also be hiding the text inside the html element, replacing it with an image from our sprite. Typical examples of this use case are action links (think delete icons, print links, RSS icons, etc.) and headings (although CSS3 and Web fonts are quickly making this technique obsolete).

.hideText{
   text-indent: -999em;
   letter-spacing: -999em;
   overflow: hidden;
}
.spriteReplace(@x, @y) {
   .sprite(@x, @y);
   .hideText;
}
.spriteReplace (@x, @y, @width, @height) {
   .sprite(@x, @y);
   .hideText;
   width: @width;
   height: @height;
}

The spriteReplace mixin simply wraps our former sprite mixin and adds a small helper mixin to hide the text from view. It’s pretty basic, but it does save us the trouble of adding the .hideText mixin manually for every instance of this use case.


Using sprites for replaced elements.

In the example above, we have a list of sharing options. For whatever reason (theming or just personal preference), let’s say we decide to use CSS backgrounds instead of HTML images. Nothing to it with the mixins we just created. Here’s the code (assuming we’re using the reference image shown earlier):

<ul class="sharing">
   <li class="twitter"><a href="#">Share [article’s title] on Twitter</a></li>
   …
</ul>
.sharing .twitter a {
   .spriteReplace(0, 0, 32px, 32px); display:block;
}

2. Inline Images

For the second use case, we’ll tackle inline images. The main problem we’re facing here is that we won’t be able to put fixed dimensions on the html element itself because we’re dealing with variable-sized content. Typical uses of inline images are for icons next to text links (for example, external links, download links, etc.), but this method can also be used for any other item that allows text to be wrapped around a sprite image.

.spriteInline(@x, @y) {
   .sprite(@x, @y);
   display: inline-block;
   content: "";
}

.spriteInline(@x, @y, @width, @height) {
   .sprite(@x, @y);
   display: inline-block;
   content: "";
   width: @width;
   height: @height;
}

We might be lacking a structural element to visualize our image, but 2011 taught us that pseudo-elements are the perfect hack to overcome this problem (Nicolas Gallagher’s eye-opening article on using pseudo-elements for background images explains everything in detail). This is why the spriteInline mixin was especially developed to be used within a :before or :after selector (depending on where the image needs to appear). We’ll add an inline-block declaration to the pseudo-element so that it behaves like an inline element while still allowing us to add fixed dimensions to it, and we’ll add the content property, which is needed just for visualizing the pseudo-element.


Using sprites for inline images.

The example above shows a list of affiliate links. The design demands that each link be limited to one line, so we can safely use the .spriteInline mixin to display the icons in front of each link:

<ul class="affiliates">
   <li class="amazon"><a href="#">Buy on Amazon.com</a></li>
   …
</ul>
.affiliates .amazon a:before {
   .spriteInline(4, 1, 22px, 16px);
}

3. Padded Images

The third and final use case comes up when text isn’t allowed to wrap around a sprite image. Typical examples are list items that span multiple lines, and all kinds of visual notifications that bare icons. Whenever you want to reserve space on a multi-line element to make sure the text lines up neatly next to the image, this is the method you’ll want to use.

.spritePadded(@x, @y) {
   .sprite(@x, @y);
   position: absolute;
   content: "";
}
.spritePadded(@x, @y, @width, @height) {
   .sprite(@x, @y);
   position: absolute;
   content: "";
   width: @width;
   height: @height;
}

Again we’ll try our luck with pseudo-elements; this time, though, we’ll be performing some positioning tricks. By applying a position: absolute to the pseudo-element, we can place it right inside the space reserved by its parent element (usually by applying padding to the parent—hence, the name of the mixin). The actual position of the image (the left, right, top and bottom properties) is not added to the spritePadded mixin and should be done in the selector itself to keep things as clean and simple as possible (in this case, by maintaining a low parameter count).

Because we’re using absolute positioning, either the :before or :after pseudo-element will do the job. Keep in mind, though, that the :after element is a likely candidate for CSS clearing methods, so if you want to avoid future conflicts (because the clearing fix won’t work if you add a position: absolute to the :after pseudo-element), you’d be safest applying the sprite style to the :before element.


Using sprites for padded elements.

Let’s assume we need to indicate that our article is available in other languages (probably on a different page or even website). We’ll add a little notification box, listing the different translations of the current article. If the text breaks onto a second line, though, we do not want it to crawl below our little icon, so we’ll use the spritePadded mixin:

<section class="notification translated">
   <p>Translation available…</p>
</section>
.translated p {
   padding-left: 22px;
   position: relative;
}
.translated p:before {
   .spritePadded(5, 5, 16px, 14px);
   left: 0;
   top: 0;
}

The Ideal Sprite

So, have we achieved CSS sprite wizardry here? Heck, no! If you’ve been paying close attention, you might have noticed that the use cases above offer no solution for adding repeating backgrounds to a sprite. While there are some ways around this problem, none of them are very efficient or even worthy of recommendation.

What CSS sprites need in order to truly flourish is a CSS solution for cropping an image. Such a property should define a crop operation on a given background image before the image is used for further CSS processing. This way, it would be easy to crop the desired image from the sprite and position it accordingly, repeating it as needed; we’d be done with these :before and :after hacks because there wouldn’t be anything left to hide. A solution has been proposed in the Editor’s Draft of the CSS Image Values and Replaced Content Module Level 3 (section 3.2.1), but it could take months, even years, for this to become readily available.

For now, the LESS mixins above should prove pretty helpful if you plan to use CSS sprites. Just remember to prepare your sprite well; if you do, things should move ahead pretty smoothly, even when deadlines are weighing on you.

(al)

© Niels Matthijs for Smashing Magazine, 2012.

0
Your rating: None

Pirate!We recently announced AIR 3.2 with Stage3D support for mobile. Some of you have asked about learning more about GPU programming, best practices and also some of you had questions regarding the BunnyMark test we had in the AIR 3.2 video.

The BunnyMark demo we showed, uses a tiny framework developed internally at Adobe (named GPUSprite). It makes use of support classes called GPUSprite/GPUSpriteLayer, which optimize rendering by allowing a large number of of sprites to be drawn in a single draw call (batching).

This means all those sprites must be able to sample their image from the same sprite sheet.  Performance is really nice.  You could extend it to multiple sprite sheets, but you will have to organize your content into layers with one layer per SpriteSheet.

All the objects on a higher layer will be rendered on top of objects on lower layers.  For a scrolling game with background, foreground, characters, effect layers and so on, it is a nice authoring solution. Of course this has way more restrictions than what Starling would allow, it actually has very limited features.

So do not consider this as a silver bullet, consider this as an example to learn how to program GPUs efficiently, or also tweak frameworks to achieve higher framerates.

You can download GPUSprite on the FP-SDK github repo.
Download the BunnyMark code (using GPUSprite).

Special thanks to Iain Lobb for the original BunnyMark.
Special thanks to Philippe Elsass for the modified BunnyMark test.

Live demo of GPUSprite below :

Get Adobe Flash player

0
Your rating: None

  

In this article, we’ll look at Scalable Vector Graphics (SVG), one of the most underused technologies in website development today.

Before diving into an example, let’s consider the state of the Web at present and where it is going. Website design has found new vigor in recent years, with the evolving technique of responsive design. And for good reason: essentially, responsive website design moves us away from the fixed-width pages we’ve grown accustomed to, replacing them with shape-shifting layouts and intelligent reflowing of content. Add to that a thoughtful content strategy and mobile-first approach, and we’re starting to offer an experience that adapts across devices and browsers to suit the user’s context.

When we look at the breadth of Web-enabled devices, responsive design is sure to provide a better user experience. Scrolling horizontally, panning and zooming the viewport have their place in user interface design, but forcing the user to do these things just to navigate a website quickly becomes tedious. Fitting the website to the viewport is about more than just layout: it’s also about resolution. In this article, I’ll demonstrate why SVG is a perfect addition to future-friendly Web development.

Introducing SVG

SVG offers a truly resolution-independent technique for presenting graphics on the Web. SVG is a vector graphics format that uses XML to define basic properties such as paths, shapes, fonts and colors, and more advanced features such as gradients, filters, scripting and animation. Create the file once and use it anywhere, at any scale and resolution.

Consider the use cases: UI and navigation icons, vector-style illustrations, patterns and repeating backgrounds. For all of these, a scalable graphic is the perfect solution from a visual standpoint, and yet fixed-resolution images are still the norm. In the example below, we’ll show you how to expand on a common development technique to take advantage of SVG.

Resolution independence with SVG

A Case Study: CSS Sprites

We all know about the CSS sprites technique. (If you don’t, then have a quick read through Sven Lennartz’ article. And Louis Lazaris points out its pros and cons.) In the example below, we’ll show how seamlessly SVG replaces normal raster images. If this technique is not for you, you can certainly imagine a whole array of similar situations in which to use SVG.

Vector icons play a big role in user interface design. Pictures express concepts with vivid clarity, whereas their textual counterparts might carry ambiguity. In UI design, where space is scarce, a simple illustrated icon could be greatly welcome.

I’ve mocked up the following example:

An icon based UI menu

I’ll be first to admit that this row of icons won’t win any design awards, but it will suffice for the sake of this article! Let’s look at the HTML:

<div class="actions">
   <a class="a-share" href="#">Share</a>
   <a class="a-print" href="#">Print</a>
   <a class="a-tag" href="#">Tag</a>
   <a class="a-delete" href="#">Delete</a>
</div>

I’ve kept the HTML to a minimum for clarity, but in practice you’d probably want to mark it up with an unordered list. And you’ll almost certainly want to replace those hashes with real URLs (even if JavaScript provides the functionality, having a fallback is nice). Let’s look at the CSS:

.actions {
   display: block;
   overflow: auto;
}

.actions a {
   background-image: url('sprite.png');
   background-repeat: no-repeat;
   background-color: #ccc;
   border-radius: 5px;
   display: block;
   float: left;
   color: #444;
   font-size: 16px;
   font-weight: bold;
   line-height: 20px;
   text-decoration: none;
   text-shadow: 0 -1px 2px #fff;
   padding: 10px 20px 10px 40px;
   margin-right: 5px;
}

.a-share  { background-position: 10px 0; }
.a-print  { background-position: 10px -40px; }
.a-tag    { background-position: 10px -80px; }
.a-delete { background-position: 10px -120px; }

Note the fixed-pixel sizing and the PNG background, which we can see below framed in full Photoshop production glory:

A PNG sprite in Photoshop

This implementation of a CSS sprite is basic, and at today’s standard, it’s not good enough! How can we enhance this? First, let’s consider the following issues:

  1. We’ve rasterized the image at a very early stage. Even at full size, icons in which points sit between pixels, such as the one for “Print,” have blurred.
  2. If we zoom in, the image will blur or pixellate even more; there is no additional data to re-render the image at larger sizes.
  3. Everything has a fixed size, which is neither good for responsive design nor good for accessibility, because the browser’s default font size is ignored.

As you’ve probably guessed by now, we’ll show you how SVG solves these problems. But first, let’s reiterate each point thoroughly to understand the issues at large.

1. Rasterization

Devices such as modern smartphones have a very high pixel density; some already surpass the 300 pixels-per-inch (PPI) mark that is assumed to be the limit of the human eye’s ability to distinguish fine details. A pixel has no real-world equivalent in size until it sits on a screen of fixed dimension (say, 3.5 inches diagonally) and fixed resolution (say, 640 × 960 pixels). At this scale, text with a font size of 16 pixels would be incredibly small to the eye. For this reason, devices simply cannot translate 1 CSS pixel unit to 1 device pixel; instead, they double up. Thus, a 16-pixel font size actually takes over 32 pixels when rendered.

The same applies to images; but they are already rasterized, so doubling up the pixels has no benefit. In our example, each icon has been rasterized at around 25 × 25 pixels (the whole sprite being 30 × 160), so they cannot take advantage of the double pixel ratio. One solution is to use CSS media queries to detect the pixel ratio. This is already implemented in Webkit- and Gecko-based browsers.

To improve our example, we can add the following CSS declaration:

@media only screen and (-webkit-min-device-pixel-ratio: 2)  {
   .actions a {
      background-image: url('sprite@2x.png');
      background-size: 30px 160px;
   }
}

The alternate background image supplied in the code above has been saved at 60 × 320 pixels (i.e. double the original dimensions). The background-size property tells CSS to treat it smaller. Significantly, now the device has the additional data to render a better image (if capable).

This solution isn’t bad, but it doesn’t solve the problems we’ll run into in points 2 and 3 below. It also requires that we maintain multiple files of increasing size: a potential burden on bandwidth and a real hassle. For non-vector images, such as photography in JPG format, we can’t do much more than that.

2. Zooming

At their default size, our rasterized icons look acceptable, at least on low-pixel-density screens. However, should the user zoom in on the Web page, these little UI delights will degrade very quickly.

A PNG sprite zoomed in and blurred.

Zooming is a common action when users find a website too small for comfortable viewing. Or, to put it another way, websites that are designed too small are very common. There is really no “perfect” size, because almost everyone has at least some level of visual impairment, since our eyes inevitably deteriorate with age. Secondly, with the rapid increase in touchscreen devices, pinch-to-zoom has become the standard way to enlarge fixed-sized content designed for larger screens (i.e. much of the Web today).

We should develop websites in a way that minimizes the need for user input — that’s where responsive design comes in (see point 3 below) — but zooming is here to stay. There’s simply no way to provide pre-rasterized images for every level of zoom (in theory, an infinite scale). Scalable graphics are the solution, and we’ll show you how to enhance our example. But first, a related word on fixed sizing.

3. Fixed Sizes

Presenting page elements at fixed sizes forces many users to zoom, but it also disables a very useful browser feature. Users can set their preferred font size (the default in browsers is 16 pixels). By sizing everything in pixels, we override this preference. Sizing elements based on this default is much better, so that, if the text is bigger, everything adjusts to match. This essentially mimics the zooming effect but happens without the user having to manually do it on every visit. Ethan Marcotte has written a great article that explains relative font sizes.

Let’s re-implement our sprite example with a solution to these three issues.

A Scalable Implementation

Here is the HTML again. We don’t need to change anything here.

<div class="actions">
   <a class="a-share" href="#">Share</a>
   <a class="a-print" href="#">Print</a>
   <a class="a-tag" href="#">Tag</a>
   <a class="a-delete" href="#">Delete</a>
</div>

The updated CSS is where the magic happens:

body { font-size: 100%; }

.actions {
   display: block;
   overflow: auto;
}

.actions a {
   font-size: 1em;
   line-height: 1.25em;
   padding: 0.625em 1.25em 0.625em 2.5em;
   margin-right: 0.3125em;
   border-radius: 0.3125em;
   background-image: url('sprite.svg');
   -webkit-background-size: 1.875em 10em;
   -o-background-size: 1.875em 10em;
   -moz-background-size: 1.875em 10em;
   background-size: 1.875em 10em;
   /* styles carried over from the original implementation */
   background-repeat: no-repeat;
   background-color: #ccc;
   color: #444;
   display: block;
   float: left;
   text-decoration: none;
   text-shadow: 0 -1px 2px #fff;
}

.actions-em .a-share { background-position: 0.625em 0; }
.actions-em .a-print { background-position: 0.625em -2.5em;  }
.actions-em .a-tag { background-position: 0.625em -5.0em;  }
.actions-em .a-delete { background-position: 0.625em -7.5em;  }

In this version, we’ve made the following changes:

  • The background-image is now an SVG file.
  • All sizes are based on the default of 16 pixels, or 1 em. If the user’s default is larger or smaller, then everything will scale relatively. (If you multiple each em size by 16, you’ll get the number of pixels used in our initial fixed-size example.)
  • The background-size is very important. By setting this in em units, we’re telling the browser to scale the sprite relative to everything else. You’ll notice that 1.875 × 10 em multiplied by 16 becomes 30 × 160 — the base size at which we produced the sprite in pixels.
  • The background-position of each sprited icon is also based on relative units.

Now that we’re using SVG and relative sizes, we have solved the three big issues highlighted above. A scalable graphic can be rasterized on demand to perfectly suit any device resolution and any zoom level. By using relative sizes, we can continue implementing a responsive design, minimizing as much as possible the need for the user to zoom. We’re also respecting the browser’s default font size, and enabling our design to adapt accordingly.

I actually produced the SVG sprite first and the PNG version from that. (I imported the SVG in Photoshop before exporting it as a PNG — Illustrator’s PNG export had very poor rasterization.) Below is the header in my SVG file. Notice the same 30 × 160 initial size.

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
   width="30px" height="160px" viewBox="0 0 30 160" enable-background="new 0 0 30 160" xml:space="preserve">

You can see that the attributes for width and height are set in pixels (width="30px" height="160px") in the opening svg tag (as generated by Adobe Illustrator). This actually causes it to render early in Firefox, before the graphic has scaled to match the em sizes in background-size. Webkit-based browsers seem to scale the SVG perfectly, regardless. I’ve found that editing the SVG file to use em units in these two attributes fixes any rendering issues in Firefox.

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
   width="30em" height="160em" viewBox="0 0 30 160" enable-background="new 0 0 30 160" xml:space="preserve">

I don’t know which browser actually implements this scaling correctly, but let it be noted that extra care is needed to ensure cross-browser perfection. Mozilla MDN has an excellent in-depth article, “Scaling of SVG Backgrounds,” which explores more practical examples. For more ideas, see Alex Walker’s article “A Farewell to CSS3 Gradients.”

Here’s a super-close screenshot showing the SVG sprite:

A close-up of a SVG sprite.

The sprite scales beautifully. (Sadly, the same can’t be said for my tacky text-shadow effect.)

It’s best to experience the joys of scalable graphics and relative sizing firsthand. I’ve uploaded a side-by-side live demo demonstrating a combination of all the techniques mentioned above.

Browser Support

At the start of this article, I said that SVG was underused. I believe that has generally been the case due to poor browser support. But things are different now! Browser support for SVG has blossomed over the last year to the point where implementing it is a viable use of development time.

According to the website When Can I Use?, support for SVG across multiple implementations is as follows (I’ve combined support for both CSS’ background-image and HTML’s img source — the most useful attributes):

  • Internet Explorer 9+
  • Firefox 4+
  • Chrome 4+
  • Safari 4+
  • Opera 9.5+

Mobile browser support is also pretty much across the board. If a workable fallback exists for older browsers, then SVG is a very viable solution.

For some of the new additions to Web standards, we can implement them safe in the knowledge that old browsers will simply ignore them and that they aren’t even required. We call this “progressive enhancement”: better browsers get a progressively better experience. SVG is slightly different, because for most practical purposes, it simply replaces other images in CSS backgrounds and HTML elements. The image format — be it SVG, PNG, JPG or GIF — is either supported or it isn’t. We can’t simply follow the practice of progressive enhancement here, because an image failing to render is not an acceptable experience.

Browser Sniffing or Feature Detection?

We could make an educated guess and say that we need to worry only about users of Internet Explorer 6 to 8. In this case, the conditional comments technique for IE-only styles enable us to re-apply a second CSS background-image of a supported format such as PNG, instead of the default SVG background.

Browsing sniffing is always a dangerous game. While Internet Explorer tends to be the main offender, we can never assume it is the only one.

The safer and highly recommended option is to detect SVG support and use it only if it’s found. I suggest using Modernizr if you need to detect multiple features. Modernizr applies a class of svg to your root html element if detected (to which you can apply SVG as a background-image). If you’re using SVG as the source of an image element in HTML, then implementation is a little harder. You’ll have to write more JavaScript to find and replace all sources once support has been established.

The problem with these methods is that the browser will download the fallback image before SVG is detected — the only exception being the conditional comments technique for IE. Users will also likely see a flash of re-styled content when the source image changes. This shouldn’t be the case for long; but at least for now, these problems may be enough to hold you off on SVG usage.

File Size

In our sprite example, the raw SVG file was 2445 bytes. The PNG version was only 1064 bytes, and the double-sized PNG for double-pixel ratio devices was 1932 bytes. On first appearance, the vector file loses on all accounts, but for larger images, the raster version more quickly escalates in size.

SVG files are also human-readable due to being in XML format. They generally comprise a very limited range of characters, which means they can be heavily Gzip-compressed when sent over HTTP. This means that the actual download size is many times smaller than the raw file — easily beyond 30%, probably a lot more. Raster image formats such as PNG and JPG are already compressed to their fullest extent.

Performance

Rendering performance is a concern with SVG, especially on mobile devices, whose hardware is limited. Raster images can be rendered pixel for pixel after decompression and de-encoding. Vector graphics need to be rasterized at a specific resolution every time they’re viewed.

SVG has consistently proved slower than Canvas as a platform for animating vector graphics; but our concern here is basic rendering, not manipulation a thousand times per second, and if that is possible, then simple rendering shouldn’t be a concern. The more intensive SVG features are things like clipping masks and filter effects. These are unnecessary for many practical purposes (like our sprite example), but, if required, the best way to check performance is by testing. A lot of Web development is supported in theory, but in practice results are far from perfect.

Alternative Methods

Hopefully you agree that SVG is extremely useful but not always the ideal solution to resolution independence. Ultimately, the trick is to avoid raster images while maintaining the scalability of visual styles. Below are a few more ideas to think about.

CSS3

You’ve probably already started combining CSS3 properties such as linear-gradient, text-shadow and box-shadow to create more complex styles. Web developer Lea Verou curates a CSS3 pattern gallery that shows off the impressive potential of gradients alone.

CSS3 gradient patterns

In his article “Mobile Web in High Resolution,” Brad Birdsall introduces a technique to maintain pixel perfection for high-resolution displays using the pixel-ratio property.

Then there are pure CSS “icons,” which Faruk Ateş rightly points out as being absolute “madness” — certainly so if you’re using CSS to create a logo! But you could argue the benefits of a small handful of very specific techniques, such as CSS triangles, as demoed by Chris Coyier.

Web Fonts

Dingbat Web fonts and look-a-like Unicode glyphs are two interesting alternatives for vector icons, both with accessibility and semantic challenges. Jon Hicks has a write-up of perhaps the best practice for this. SVG seems a more appropriate technique for icons, but both have an immediate visual impact at high resolutions — and we’ll be paying increasing attention to that in coming years.

Looking Forward

As you can see, SVG usage is very much a possibility, and browser support and performance will only improve in future. What’s important to note from this article is that we really should be building websites that are as resolution-independent as possible.

Consider the “one Web” philosophy and the vast range of devices we use to access it — there is no single user experience. The more we can do to stay device-agnostic, the better. Responsive website design addresses many of these needs and certainly provides many benefits. Using vector graphics may not be as apparent, but its little improvements really do make a difference.

With today’s level of support, many users can experience the beauty of crisp scalable graphics… or perhaps that’s the wrong way to think about it. Most users won’t say “Wow! Kudos on the vectors.” To our dismay, they probably wouldn’t even consider them (and certainly wouldn’t recognize the effort required to craft them). And that’s a good thing; each time we improve the user’s experience, we don’t necessarily need to make a song and dance about it. Letting things continue to grind away under-appreciated is OK. It’s the lack of such things that gets recognized and sniffed at. Raise the user’s expectations in visual aesthetics, and they’ll start to notice the websites that do look shoddy. If you don’t do it, others will.

(al)

© dbushell for Smashing Magazine, 2012.

0
Your rating: None

Integrating images as menu items

The ability to have images as menu items sounds like a common and straight forward task. Surprisingly, Drupal never has had this ability built into core, but there are a few modules that will help us accomplish our goal. Sprite Graphic Menu is probably the easiest one to use and the one that will be covered in this article.

It is possible to write some custom code using regex in your template.php which could parse the title field of a menu item to look for image filename extensions and then alter the menu output to print that menu item as an image. But wouldn't it be nice if a module could extend the current menu system and provide an image upload field. Even better, how about some CSS options to provide our own sprite background positioning. This is exactly what Sprite Graphic Menu does for us.

The current process is a bit janky and will hopefully be improved. Example: You will not see the image upload field when first creating a menu item. You must create the menu item and then edit it, then the image upload and configuration options will be displayed on the form.

Screenshot of Sprite Menu Graphic Configuration

0
Your rating: None

<p>In a new research paper, Microsoft&rsquo;s Johannes Kopf and The Hebrew University&rsquo;s Dani Lischinski describe a new algorithmic method for converting pixel art into sweet, smooth vectors.</p>
<p><a href="http://www.geekosystem.com/depixelating-pixel-art-algorithm/">Check it!</a></p>

0
Your rating: None

Flash retro TV effect, Flash CRT television effect for video and other display objects, ActionScript 3 CRT TV effect, Flash AS3 old TV effect for any display object, Real time old TV in Flash, Flash CS4 tutorial, Old TV code in AS3 Flash, Old TV effect in Flash ActionScript 3, Bitmap effects in Flash, Flash AS3 Video effects, Flash CS4 Tutorials, ActionScript 3 Tutorials

0
Your rating: None

Steve Souders posted on Runtime Page Optimizer a tool that you can think of as a performance proxy. It sits on the server side, and cleans up content before it is sent back to the browser.

What can it do? Steve let us know:

RPO automatically implements many of the best practices from my book and YSlow, so the guys from Aptimize contacted me and showed me an early version. Here are the performance improvements RPO delivers:

  • minifies, combines and compresses JavaScript files
  • minifies, combines and compresses stylesheets
  • combines images into CSS sprites
  • inlines images inside the stylesheet
  • turns on gzip compression
  • sets far future Expires headers
  • loads scripts asynchronously

RPO reduces the number of HTTP requests as well as reducing the amount of data that is transmitted, resulting in a page that loads faster. In doing this the big question is, how much overhead does this add at runtime? RPO caches the resources it generates (combined scripts, combined stylesheets, sprites). The primary realtime cost is changing the HTML markup. Static pages, after they are massaged, are also cached. Dynamic HTML can be optimized without a significant slowdown, much less than what’s gained by adding these performance benefits.

Steve had another couple of interesting posts recently:

  • Say no to IE6 discusses how we need to do something to help upgrade IE6 users (to IE7 is fine!)
  • Raising the bar talks about results from Steve's UA Profiler tests and how new browsers are pushing forward
0
Your rating: None