SVG

Small demo of animated CSS Mask Icons. Note: It uses the non-standard CSS masks that are only implemented in WebKit without a spec. I don’t wanna go into discussing if that’s ok or not, instead I just like to experiment with them because I think you can do cool stuff and hopefully one day it will become standard. Update: Happy that there is now a CSS Masking Spec.

Using CSS masks for icons would have the benefit of being able to create a large icon-set and easily swap textures, colors, shadow effects. And also animate them. Basically everything you can do with CSS backgrounds. It could also be used for other stuff like tooltips, speech bubbles, funky shaped buttons and so on.

The basics of this demo goes something like this:

  1. Add a texture and gradients to your element’s background.
  2. Use SVG (or PNG) as mask-image to “cut out” the rectangle into the desired shape.
  3. Use a second shape together with mask-composite to either add  (source-over -> robot), subtract (source-out -> apple bite, cloud arrow) or intersect (xor -> cloud arrow while pressing) with the first mask.
  4. Add some transitions/animations to the mask-position.

So ya, basically you can mask a mask, combine multiple masks or even do the opposite depending if they overlap or not. In total there are a dozen mask-composite options that I’m not quite sure what the exact difference is. I just tried them all till it worked like I wanted. ;-)

Couple notes:

  • Pseudo elements (highlight on the cloud) also gets masked.
  • CSS filters (Chrome Canary, WebKit nightly) work great with CSS masks, unlike box-shadows. See how the drop-shadow follows the contures of the SVG shape.
  • For better cross-browser support you could just animate multiple backgrounds (background-composite works too), but then you loose the ability to use a seamless texture.
  • I’m pretty sure, you could do all the effects with SVG alone. It has masks, drop-shadows, animation.. I just haven’t really dugg myself deep enough into them.
  • Since it uses mask-position to animate the masks, you can’t rotate them, which is a little limiting.

See demo (WebKit)

SVG Stacks

Image sprites are wildly used for downloading lots of icons or UI elements all at once with just a single HTTP-Request. But they are somewhat cumbersome to use because you have to calculate the background-position offsets. You can’t easily add, remove or reorder them without recalculating. Or change the size without a neighbour peeking in from the side.

How could it be solved? Well, by stacking them all on top of each other, turn off their visibility and only show the one you want. Have been wishing this would be possible for a while.. and then this happened (read from below):

image

Oh, nice! The demo already works in Firefox. That’s great news.

There are alternatives to SVG Stacks with better browser support by using embed, iframe, object or img elements, but I still prefer background images because of their easier positioning/resizing. So let’s hope more browsers will also add support for that.

So how does it work? It’s actually pretty simple. Have a look at the source of Erik’s SVG file

image

First we give each of our icons in the SVG file a unique ID and the same class name, add some CSS to hide all icons and only display the one that gets selected with :target. And now we can use a hash in the URL to pass the ID into the SVG file, like background: url(icon.svg#ID).

Big thanks to @erikdahlstrom for that technique.

Update: A couple bugs have been added to other browsers so you can track its progress. Opera: “CORE-37596” (no public link). WebKit’s Bugzilla : 91790, 89983, 89985. And please star it in Chromium Issue 128055.

Update II: Michael Schieben created a tool to that turns a folder of SVG files into a single SVG Stack: SVG Stacker

Update III: Looks like “SVG Stacks” got shot down by the WG. But there is still some hope left and it’s probably still in flux. So instead of url() we could use image().

We’re in an icon-sharpness limbo

With the rise of Retina displays people are looking for resolution independent alternatives to PNG icons. Some fell in love with font-icons, some are shouting “SVG”. But I’m sorry, if you’re looking for a silver bullet, I’m afraid it doesn’t exist. Let’s take a closer look at our options:

Icon fonts are awesome, but.. 

they are not sharp. I mean really sharp, pixel-perfect kind of sharp. Using font-face for icons has become quite popular. I have been promoting and even started collecting them. But there is a flaw that keeps bugging me. They are still a tiny bit blurry on “non Retina” displays (which are still a huge majority). Try out the size slider in Chris’s demo and take a very close look. It varies at different sizes, but they all have this “half-pixel blurriness” problem. It might be hard to notice, so here a zoomed-in screenshot at 15px (also removed the background noise):

The subpixel anti-aliasing works great on curves, but not on straight lines, there it just doesn’t look sharp. In theory you could use font hinting to snap the icons to whole pixels. But so far I’m not aware of any icon-set doing that. Also I’m guessing it’s a lot more work and the hinting data might increase the file size significantly. Edit: @thijs notes that hinting only works on supported platforms and won’t help on OS X, iOS and Android.

SVG to the rescue?

Well, not really. The big advantage of using SVG icons would be that in their original size (not resized), they look pixel-perfect sharp. But once you start resizing, they have the same subpixel blur problem until you reach multiple of its original size. Notice the inner cross.

In practice using only multiple sizes probably should be ok. You create all your icons in a base size, let’s say 16px and you use a bigger version for action buttons in 32px or 48px.

Edit@erikdahlstrom + @Marco_Rosella mentioned: shape-rendering:crispEdges. If used on individual rect(angles), they can be forced to pixel-snapping. Might not always be perfect, but keeps it crisp. Test in this jsFidde.

Problem solved? I wish, but there are other issues like:

  • There is not a lot of good SVG icon sets available.
  • Lack of SVG sprite creation tools.
  • Can’t change the color with CSS. It is possible, but only when used with inline SVG and I don’t feel happy adding big SVG chunks to the markup.
  • No effects.. like drop shadows. (SVG has filters, but again.. you can’t easily change them in CSS).
  • And the biggest bummer of all.. bad browser support in Firefox and Opera when an SVG is used as a background-image. It appears that the SVG actually gets converted into a bitmap and when resized with background-size, it doesn’t get redrawn, just scaled up, which makes it look really blurry. This kinda defeats the purpose of using a Scalable Vector Graphic.

Here a fiddle to test it out.

You could use inline SVG or SVG as an <img> element, but that makes it hard to be used as a sprite. Maybe with nested elements and overflow:hidden? Anyways.. just not as straight forward and flexible as with background-image.

Edit: David Bushell found a workaround by starting large and only scale down.


PNGs

Lots of icon fonts also come with a PNG version that you could use instead, but then you need a solution for showing a HiRes version on Retina displays. Using a device-pixel-ratio Media-Query should help you out. Or Apple just implemented -webkit-image-set, which looks promising, but still is gonna take a while.

So what should you do? As I said.. there is no silver bullet, but..

Here a little guide that might help.

  1. When starting a new project, during prototyping and development, use font icons. Nothing beats the freedom of quickly and easily swap icons, change colors, try out text-shadow and other effects.
  2. Then at some point you have to decide if it’s worth the trouble that comes when using SVG icons or PNGs. It’s a tough call and in the end it all depends on your requirements and priorities. It almost needs a flow-chart. ;-) You’ve to be ok with all their limitations described above. See if the available budget allows for the extra work, count how many icons there are in total and if you need them in different sizes or not.

There’s just no single image format suitable for everything and probably never will be. So who says you can’t mix them all together? Maybe best is to use PNG served in many different sizes for your high fidelity, multi-color logo and other graphics. SVG icons for your navigation that stays the same size, but also look sharp on Retina displays. Responsive inline SVG for bars and charts and an icon font for all your different button sizes. We’ve mostly been doing that anyways.

A look into the future

Is there a way to get out of this icon-sharpness limbo? Well.. let’s just wait a little.. once we have Retina displays everywhere (ok, could take a couple years), the subpixel problem will be gone and maybe browsers will have fixed the SVG issues and we can truly celebrate our resolution independent icons? But even then, we still would’ve to deal with the problem that details in icons don’t scale. Update: Media Queries in SVG might solve that.

In case I’m missing something, you can send a Tweet or write a comment on G+. Thanks.

simurai simurai

I’m a UIX Designer and like to experiment with CSS3. This site is my personal playground.

About
Contact