Rethinking Responsive SVG

Advertisement

If you haven’t seen Joe Harrison1’s responsive icons2 technique yet, you’ll most probably be impressed as much as I was when I first discovered it. In this article, I’d like to explore what we can do with SVG beyond “traditional” scalable vector graphics that are used to replace bitmap PNGs. In fact, we can see SVG as an independent module that encapsulates CSS for the customization of views as well as the responsive behavior that also encapsulates JavaScript for the interaction logic.

Now, let’s dig a bit deeper into this technique.

Responsive SVG: The Hobo’s Method

Harrison’s Responsive Icons website is implemented pretty simply. It follows a well-known technique, image sprites. If you’re not familiar with sprites, let me explain. Image spriting is a technique that was previously used only for raster images to combat poor network performance. The idea is to combine a lot of small images into a single file, so that the client has to download only a single image from the server.

You would also use CSS to shift the image around and display only the part that you need for a particular element, saving the user the overhead of having to download every image individually. (Read more about sprites on CSS-Tricks3.)

Harrison’s technique does the same thing, except with SVG instead of PNGs. This is what all of his icons combined into a single file would look like:

All Icons combined in a single SVG file.4
All Icons combined in a single SVG file. Large View5.

This file, then, would be set as the background of a container in which one of these icon would need to be displayed:

.icon {
  width: 300px;
  height: 300px;
  background: url(../images/home_sprite.svg);
  background-position: center top;
}

The example above is simple enough but has some problems. The solution is not portable enough. In fact, two parts are needed to make the method work: external CSS and an SVG sprite.

Responsive SVG: The Poor Man’s Method

Because CSS can be defined within SVG itself, let’s revise the example above to encapsulate the icon and to make it portable.

First, let’s remove all of the spatial shifts of the icons in the sprite. Of course, that leaves us with a layered mess of icons:

See the Pen inxym6 by Ilya Pukhalski (@pukhalski17147) on CodePen18158.

Then, let’s rearrange all of the shapes and group them by icon, adding an .icon class to each group, as well as numbers to be able to identify each one we want (so, #home_icon_0, #home_icon_1 and up to #home_icon_8):

<svg>
  <g id="home_icon_0" class="icon">
    <!-- paths and shapes -->
  </g>

  <!-- ... -->

  <g id="home_icon_8" class="icon">
    <!-- paths and shapes -->
  </g>
</svg>

Now, we’re ready to add media queries, so that we can select the icon in the SVG file that we want to display. For this purpose, writing the CSS directly in the <svg> tag is possible using <defs> tags.

<svg>
  <defs>
    <style>
    /* Hide all of the icons first. */
    .icon {
      display: none;
    }

    /* Display the first one. */
    #home_icon_0 {
      display: block;
    }

    /* Display the desired icon and hide the others according to the viewport's size. */
    @media screen and (min-width: 25em) {

      #home_icon_0 {
        display: none;
      }

      #home_icon_1 {
        display: block;
      }
    }

    @media screen and (min-width: 30em) {
      #home_icon_1 {
        display: none;
      }

      #home_icon_2 {
        display: block;
      }
    }

    /* And so on */

    </style>
  </defs>

<!-- Icon groups go here -->

</svg>

As a result, the same icon now adapts to the viewport’s size — except now, the CSS rules, media queries and SVG shapes are all encapsulated in the SVG file itself. Resize your browser to see how the example below works:

See the Pen uxIKB9 by Ilya Pukhalski (@pukhalski2010) on CodePen2111.

Responsive SVG: The Man With A Gun’s Method

The example above looks better than the first one, but questions remain:

  • Could the responsive SVG be delivered in a better way?
  • Is following a responsive approach for laying out the icons and customizing elements possible, rather than just hiding and showing parts of the file?

Looking to the content choreography12 and layout restructuring tricks that we rely on for responsive Web design on a daily basis, we can improve our prototype even still. We’ll use responsive design, shape restructuring and transformations to adapt the icons to different viewport sizes.

First, let’s redraw the biggest and most detailed house icon in our SVG sprite file, splitting all of the paths and joined shapes into elemental shapes. The result is much more readable, and applying any transformations to any part of the icon is now possible:

See the Pen Azqyn13 by Ilya Pukhalski (@pukhalski17147) on CodePen18158.

Our redrawn icon looks the same as the biggest one from the sprite but contains many more shapes and takes up a bit more space. The magic is that we’ll add media queries and transformations to the new variant, transforming the shapes of the icon itself to get the same result as the SVG sprite:

<svg>
  <defs>
    <style>
    @media screen and (max-width: 65em) {

      #door-shadow, #tube-shadow, .backyard {
        display: none;
      }

      #door-body {
        fill: white;
      }

      #door-handle {
        fill: #E55C3C;
      }

      #door-body, #door-handle {
        -ms-transform: translate(0,0);
        -webkit-transform: translate(0,0);
        transform: translate(0,0);
      }

      #window {
        -ms-transform: translate(0,0) scale(1);
        -webkit-transform: translate(0,0) scale(1);
        transform: translate(0,0) scale(1);
      }

      #house-body {
        -ms-transform: scaleX(1) translate(0, 0);
        -webkit-transform: scaleX(1) translate(0, 0);
        transform: scaleX(1) translate(0, 0);
      }

      #tube-body {
        -ms-transform: translate(0, 0);
        -webkit-transform: translate(0, 0);
        transform: translate(0, 0);
      }

      #tube-upper {
        -ms-transform: translate(0, 0);
        -webkit-transform: translate(0, 0);
        transform: translate(0, 0);
      }
    }

    /* And so on */

    </style>
  </defs>

<!-- Icon groups go here -->

</svg>

Once we’ve added a bit of transformation magic, the icon will behave just like Joe Harrison’s SVG sprite but will contain all of the logic within itself. Open the example below in a new window and resize it to see all of the icon variants.

See the Pen hFLDG16 by Ilya Pukhalski (@pukhalski17147) on CodePen18158.

Adapting the Icon to the Parent Container’s Size

One more thing. Making the icon respond to changes in its parent container (at least the width and height) is possible, too.

To do this, first, I tried to load the SVG file in an img element, wrapped in a div. But not even one media query in the SVG file seemed to work.

My second attempt was to load the icon in the flexible object element, wrapped in a div. Doing that made all of the media queries work. And making an object fill the space of its parent is now possible, too. (Don’t forget to set the width and height attributes of the svg element to 100% or to remove them completely.)

<div style="width: 100%; margin: 0 auto;">
  <object>
    <embed src="responsive3.svg" style="width: 100%; height: auto;" />
  </object>
</div>

As for other ways to embed SVG with media queries and transforms, you could use SVG as a background image for any block element. Inline SVG is allowed as well, but the media queries would respond to the viewport.

The example below demonstrates how the icon responds to different container sizes. The media queries in the SVG handle how the icon is drawn, according to the dimensions that the SVG is to be rendered in. Here are eight blocks with different sizes, embedded with one and the same SVG file.

See the Pen hszLl19 by Ilya Pukhalski (@pukhalski2010) on CodePen2111.

Adding JavaScript to SVG

More good news! The SVG file may encapsulate not only CSS, but JavaScript, too. In essence, we can regard an included SVG file as an independent module to which any old markup language may be applied.

JavaScript in SVG will work perfectly when embedded inline in the <object> element. Such a wonderful world, huh?

Browser Support

This last and most complex method of using SVG with media queries and transformations behaves perfectly in the following browser versions:

  • Internet Explorer 9+
  • Firefox 17+
  • Chrome 17+
  • Opera 15+
  • Safari 6.0+
  • Safari on iOS 6.0+
  • Android browser on Android 3.0+

The technique might work in the old versions of browsers, but some transformations, such as scaling, wouldn’t be applied.

Conclusion

Responsive SVG icons can be used in a lot of ways, including the following:

  • responsive advertisements (the ad content would occupy the space given to it by the document, and considering that CSS and JavaScript are allowed, most of the action would be contained to a single SVG file per ad);
  • logos;
  • application icons.

I should state that nothing is wrong with the sprites technique proposed by Joe Harrison. It works, and it’s necessary for some purposes!

Thoughts? Feedback? I look forward to your input in the comments section below.

Cheers, and have fun!

(al, ml, il)

Footnotes

  1. 1 http://www.joeharrison.co.uk
  2. 2 http://responsiveicons.co.uk
  3. 3 http://css-tricks.com/css-sprites/
  4. 4 http://www.smashingmagazine.com/wp-content/uploads/2014/03/1-giant.png
  5. 5 http://www.smashingmagazine.com/wp-content/uploads/2014/03/1-giant.png
  6. 6 http://codepen.io/pukhalski/pen/inxym
  7. 7 http://codepen.io/pukhalski
  8. 8 http://codepen.io
  9. 9 'http://codepen.io/pukhalski/pen/uxIKB'
  10. 10 'http://codepen.io/pukhalski'
  11. 11 'http://codepen.io'
  12. 12 http://www.smashingmagazine.com/2013/04/25/maintain-hierarchy-content-choreography/
  13. 13 http://codepen.io/pukhalski/pen/Azqyn
  14. 14 http://codepen.io/pukhalski
  15. 15 http://codepen.io
  16. 16 http://codepen.io/pukhalski/pen/hFLDG
  17. 17 http://codepen.io/pukhalski
  18. 18 http://codepen.io
  19. 19 'http://codepen.io/pukhalski/pen/hszLl'
  20. 20 'http://codepen.io/pukhalski'
  21. 21 'http://codepen.io'

↑ Back to topShare on Twitter

Web designer/Web developer with 8 years of experience in different areas of the Web starting from UX and ending with server-side programming. JavaScript and Web standards lover, speaker. Currently specializes on cross- platform and mobile front-end development (AWD, RWD, Web, hybrid and native mobile applications).

Advertising
  1. 1

    I simply LOVE neat tricks like this. SVG is the future, I would love to try this out with responsive ads. It’s unbelievable how many ad services don’t support responsive SVG. Google Adsense has implemented the feature without SVG, but not well as it offers little control. SVG would solve that issue.

    0
  2. 2

    Nice article, clear and simple.

    I just started to tickle SVG images in responsive environnement myself. So maybe it is a noob question, nevertheless:
    Is it possible to use your exact same technique (container resize + media queries) but with CSS in an external file?

    I’m not really fond of inline style injected in SVG.

    Thx in advance

    0
    • 3

      Hi Kaïros.

      Definitely, yes. You can use external CSS file like this:
      <?xml-stylesheet type="text/css" href="main.css" ?>

      I just used inline CSS for illustrative purposes as well as to keep it inside single CodePen.

      -1
  3. 4

    I really like the way SVGs scale and can be crisp – and how easy it is to get from your vector design program to the asset. However I find the render performance when using for SVG is very slow… so apart from an icon or two here and there I tend to avoid SVG until the browser gets better at handling them.

    -2
    • 5

      Nicolas Froidure

      March 5, 2014 8:30 am

      @Chris I strongly agree with you. I experienced the same kind of slowness while embedding SVG.

      Some tips can help sometimes to having more performant integrations:
      - Clone elements instead of duplicating them (Alt D instead of Ctrl D in Inkscape, use element under the hood)
      - Avoid pointer events in the SVG by adding this CSS line when listening to events is not necessary:
      * { pointer-events: none }

      -1
    • 6

      I really hope browsers start speeding up SVG rendering. My group ran into this issue when converting Vector training content from flash to HTML5 and we could barely get HTML5 to render 1 frame every two seconds. The vector artwork was quite complex, but Flash handled it with ease for years. The browser chokes on it. We wound up rasterizing the content to make it play smoothly in HTML5.

      -3
  4. 8

    I wish SVG fragment identifiers came to Google Chrome, Opera and Safari. It would be easier to make SVG stacks.

    2
  5. 9

    I created a (somewhat) similar experiment a while ago. I played around with the idea of stacking all your icons on top of each other and saving them as a single SVG template.
    http://codepen.io/chrisnager/pen/ouBga

    In the template, all the icons would be flattened and cut into tiny pieces. You’d reuse the template anytime you needed an icon. The icon’s class would dictate which pieces were filled with color to show your chosen icon.

    -1
    • 10

      I’ve just seen your pen after reading the comments on this page (http://www.smashingmagazine.com/2014/03/05/rethinking-responsive-svg/). To my mind the article, though well written and informative is counter-productive and undermines the point of having SVG’s in the first place.
      They are called scalable vector graphics after all.

      Why on earth would we want to complicate our CSS for various screen sizes for a component which is already responsive?

      Even for design purposes or aesthetic factors, , , & the tags allow you to call part of the svg graphic or all paths without the need to embed objects, iframes or images or to create sprite sheets.

      I’m discovering that the potential for SVG is far more than simple styling elements and your pen as is may seem a mess to the untrained eye but you could have foregone the 2nd column and just stacked them one on top of the other and simply placed them where you need on the page – even fills,strokes and colors could be styled individually. Yes it may seem a lot of work, but if thought out properly, you could create all the graphics of website, including UI/UX in one SVG file and call them into action where and when you want them within the HTML itself.

      I think you’re on to something here and I share your doubts concerning performance -I reckon time will tell or someone actually goes out and proves whether this method is viable or not.

      Thanks for sharing.
      Ace

      3
  6. 11

    I too am loving SVG – http://snapsvg.io/

    -1
  7. 12

    I love this kind of stuff. It is amazing use of the technology afforded to us. One drawback to the “The Man With A Gun” approach is that it requires much more coordination between developer and designer if not forcing them to be one and the same person. Whereas with the sprite method, the developer simply provides the designer with a framework (8 icons – 64px, 32px … 8px) and the designer creates them and the developer can work seperately but continue to move forward.

    Great stuff though. Keep it coming.

    1
    • 13

      Mark F. Simchock

      March 5, 2014 8:00 pm

      re: “it requires much more coordination between developer and designer if not forcing them to be one and the same person.”

      Yeah, gawd forbid design should know and understand what “manufacturing” is doing :) {sarcasm}

      5
    • 14

      I reckon the day where the designer-developer boundary disappears is not that far into the future…

      0
  8. 15
  9. 16

    I like this as a proof of concept, (and this tutorial is very good/well written) but I kind of have a problem with its sentiment in practice.

    Surely the least detailed icon is the most successful icon; it conveys the concept it attempts to represent with the least amount of visual information. Anything beyond the point of recognition is waste, in a practical sense.

    I’m very enthused/interested by all of the SVG things I’ve been seeing recently, but I don’t know if I can see this kind of scaling of detail being something I love.

    -1
    • 17

      Mark F. Simchock

      March 5, 2014 8:04 pm

      fwiw, I agree with you.

      It goes without saying that there’s something to be said for consistency. That is consistency of experience across all screen sizes.

      I’m sure there are instances where this effect / technique makes sense. However, my general reaction is: Just because you can, doesn’t mean you should.

      0
    • 18

      I think the use case that justifies this effort would not necessarily be an icon. For instance, in pages with graphs and charts, more detailed drill-downs and labels could be shown only when screen size allows it.

      0
  10. 19

    Just read about an icon system on Hacker News that leverages these techniques. https://useiconic.com/icons/

    -1
  11. 20

    Seems that IE10 on Windows Phone 8 does not support it, the object tag…

    -1
  12. 26

    Thanks for good sharing. I come to know about svg international module. Really, it is very much informative to us.

    -1
  13. 27

    In all honesty, I think the Poor Man’s Method is the most effective and has the least amount of fine-tuning to achieve a manageable result. Inline media queries just make the whole page seem bloated and unwieldy (on top of the sometimes already bulky SVG).

    0
  14. 28

    Whoa. Super helpful article, and a great new way to look at SVGs. We’ll definitely be adding this to our bag of tricks.

    -1
  15. 29

    I’m new to SVG, and I hadn’t thought of doing this, very clever. Extrapolating the idea somewhat (without testing it), I know that SVG files can also reference or embed raster images. Wouldn’t layering of same sized raster images be a valid, and great solution to different raster image versions for different screen sizes too?

    It occurs to me that by defining a symbol containing a hi-res image, different layers could reference the same symbol using SVG to create different crops of that image. In size terms this wouldn’t be disimilar to favouring a lower quality hires image over multiple images, but preferential cropping within the same aspect ratio would be possible.

    Is this correct, or am I getting ahead of myself somewhat?

    Cheers,
    Mark, ia.uk.com

    -1
  16. 31

    Little warning:
    I tried using SVG xml for rendering items such as rating stars, whose fill needed to be dynamic. I thought this would be great, avoiding JS altogether for displaying content, since I could set the fill amount with php.

    However… It worked well as long as I only had one image in the page, but in a Masonry type of layout, webkit had issues with disappearing SVG. Some, but not all, of the renderings would disappear.

    3
  17. 33

    Seriously one of my favorite developer articles I have read in a while. So many new ideas and possibilities. I didn’t know a min-width media query would apply the the embed size like you did. That has so many possibilities. I’m excited to try this! Thanks.

    1
  18. 34

    The last example does not work for me, Chrome 35.0.1870.2 Mac. Only empty rectangles. All the others work.

    Last one DOES work in Safari 7.02.

    0
  19. 37

    Nice! This is a good example for icons in SVG use.

    But… Today, I still think a Icon Font one better solution, the support is larger and is very simple for implement.

    SVG is a good solution for projects that need a detailed Icons.

    -1
  20. 39

    Can anyone comment if the ability to include javascript in svg is the reason Google has prohibited the relaying of svg images with their new image proxy in gmail? They do not seem to list any documentation on the image proxy service.

    -1
  21. 40
  22. 41

    Can we use SVG format for All Product images on E Commerce site?

    -1
    • 42

      yeah you can but it will be performance issue. beside this, svg will take more time and cost.

      -1
  23. 43

    What about using a webcomponent, for example based on Polymer (http://www.polymer-project.org/) and use Harrison’s approach? Wouldn’t that be easier and have all code within one portable component?

    -1
  24. 44

    Is there any way to make SVG scale with text if?
    If you are using em in line height and zoom in, text will just stop scaling at some point, but SVG image size will keep on decreasing creating a gap between image and text (basically padding between image and text increases)

    -1
  25. 45

    Jack (@jackfilose)

    April 30, 2014 12:23 pm

    Nice article, I especially like the possibility of SVGs as a responsive advertising solution – an area that drastically needs advancing!

    Also – thought you might be interested, I recreated this responsive icon set purely with CSS (no images/SVG) in this pen: http://codepen.io/jackfilose/pen/EqjFl/

    Wasn’t exactly the most efficient process but what do you think of using the potential rendering power of browsers to display graphical elements like this? Initially very labour-intensive but I think, in larger projects, the performance benefits of not having to make requests for assets could be worth it… Especially for high-repetition units that could be wrapped in a mixin and injected as needed.

    -1
  26. 46

    Very interesting article. It opens a lots a new opportunities. Thx!

    0
  27. 47

    Hello Ilya, I m in need of help. I’ve added svg while printing my application pages using .
    Now the issue is in Chrome I can see the svg across all pages of print. But in Mozilla Firefox, only on first page of print I m able to see the svg. Please let me know what can be done for this issue.

    0

Leave a Comment

Yay! You've decided to leave a comment. That's fantastic! Please keep in mind that comments are moderated and rel="nofollow" is in use. So, please do not use a spammy keyword or a domain as your name, or else it will be deleted. Let's have a personal and meaningful conversation instead. Thanks for dropping by!

↑ Back to top