Sara Soueidan: Styling and Animating Scalable Vector Graphics with CSS [CSSConfUS2014]

1,236 views

Published on

Scalable Vector Graphics, or SVGs, are the new "big thing" in web design today, and for a good reason. With the proliferation of retina screens and high resolution displays, we need to adopt techniques that allow us to serve graphics that look good on all screens in all circumstances, and because SVGs offer resolution-independent, fully scalable and crystal clear graphics, it is safe to say that they are the future graphics format of the web.

In this talk we're going to see how SVGs can be styled in CSS, and how they can be animated using CSS animations and transitions. We're also going to cover "responsifying" SVGs using CSS media queries, and how we can control the size and looks of SVGs allowing them to adapt to different screen sizes. We'll cover a short workflow from a vector graphics editor to a responsive animated graphic on screen.

Published in: Software

Sara Soueidan: Styling and Animating Scalable Vector Graphics with CSS [CSSConfUS2014]

  1. 1. Styling & Animating Scalable Vector Graphics with CSS CSSConf - May 27th 2014, Florida @SaraSoueidan / sarasoueidan.com
  2. 2. Hello, I’m Sara.
  3. 3. Scalable Vector Graphics (SVG) is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation.
  4. 4. Why SVGs? ➔ SVGs are accessible ➔ Scalable & Resolution Independent ➔ Very Good Browser Support ➔ Smaller sizes (can be gzipped) ➔ Built-in Graphics Effects (Blend Modes, Filters, etc.) ➔ Interactive and Styleable (CSS and Javascript) ➔ SVGs Have Tools
  5. 5. Creating SVGs Adobe Illustrator Inkscape (Free) Sketch (Mac OS X only)
  6. 6. Optimize Exported Code (Standalone Tools) http://goo.gl/0XvzHs SVG Editor by Peter Collingridge (Online)
  7. 7. Optimize Exported Code (Standalone Tools) SVG O (NodeJS-Based + GUI)
  8. 8. Peter’s SVG Editor
  9. 9. Clean Up & Give Classes bird.svg Replace generic class names with semantic ones that describe your illustration.
  10. 10. Styling SVGs with CSS
  11. 11. SVG Presentation Attributes <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300px" height="300px" viewBox="0 0 300 300"> <polygon fill = "#FF931E" stroke = "#ED1C24" stroke-width = "5" points = "279.1,160.8 195.2,193.3 174.4,280.8 117.6,211.1 27.9,218.3 76.7,142.7 42.1,59.6 129.1,82.7 197.4,24.1 202.3,114 "/> </svg> star.svg
  12. 12. Shared with CSS SVG-only font font-family font-size font-size-adjust font-stretch font-style font-variant font-weight direction letter-spacing text-decoration unincode-bidi word-spacing visibility text-rendering writing-mode clip-path mask opacity filter pointer-events image-rendering clip color cursor display overflow clip-rule flood-color flood-opacity stop-opacity kerning text-anchor color-profile color- rendering fill fill-opacity fill-rule marker marker-end marker-mid marker- start stroke stroke-width stroke-opacity stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit alignment-baseline baseline-shift shape-rendering glyph-orientation-horizontal glyph-orientation-vertical color-interpolation color-interpolation-filters dominant-baseline lighting-color stop-color enable-background http://goo.gl/LVkev
  13. 13. Inline Styles (style=” ”) <svg xmlns="http://www.w3.org/2000/svg" version="1.1" style=”width: 300px; height: 300px;” viewBox="0 0 300 300"> <polygon style = ”fill: #FF931E; stroke: #ED1C24; stroke-width: 5;” points = "279.1,160.8 195.2,193.3 174.4,280.8 117.6,211.1 27.9,218.3 76.7,142.7 42.1,59.6 129.1,82.7 197.4,24.1 202.3,114 "/> </svg> star.svg
  14. 14. Embedded Styles (<style>) Inside svg <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300px" height="300px" viewBox="0 0 300 300"> <style type=”text/css”> <![CDATA[ selector {/* styles */} ]]> </style> <g id=”..”> … </g> </svg> filename.svg
  15. 15. Embedded Styles (<style>) Outside svg <!DOCTYPE html><!-- HTML5 document --> <html> <head> ... </head> <body> <style type=”text/css”> /* style rules */ </style> <!-- xmlns is optional in an HTML5 document --> <svg version="1.1" viewBox="0 0 300 300"> <!-- SVG content --> </svg> </body> </html> filename.html
  16. 16. External Style Sheets <?xml version="1.0" standalone="no"?><?xml-stylesheet type="text/css" href="style.css"?> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width=".." height=".." viewBox=".."> <!-- SVG content --> </svg> filename.svg
  17. 17. Style Rules (Selectors) Type Selectors: g {/* style a group */} circle, rect { fill: #009966; } Class and ID Selectors: .arrow-head { /* styles */ } #bird { /* styles */ } Dynamic Pseudo-Class Selectors: .icon:hover, .icon:active, .icon:focus { /* styles */ } Pseudo-Class Selectors: :first-child, :last-child, :nth-*- child(), :visited, :link and :lang, :last-of-type, :first-of-type, :not(), :nth-*-type(), :only-child, :only-of- type, ... Children Selectors: g > circle {/* styles */} Notes: Pseudo-elements/Generated Content don’t work.
  18. 18. Style Cascades http://goo.gl/QHFp6w Presentation attributes count as low level “author stylesheets” and are overridden by any other style definition (external stylesheets, document stylesheets and inline styles). <circle cx="100" cy="100" r="75" fill="blue" style="fill:deepPink;" />
  19. 19. Example: Simple Hover Effect (Iconic) Changing the stroke color and stroke width. Fading background in on hover. http://goo.gl/Fofspo
  20. 20. Embedding SVGs
  21. 21. http://goo.gl/oiYssv 1 <img src=”image.svg” alt=”Site Logo” /> 2 <object type="image/svg+xml" data="image.svg"> <img src=”fallback.jpg”><!-- fallback --> </object> 3 <embed type="image/svg+xml" src="image.svg" /> 4 <iframe src="image.svg"> <!-- fallback here --> </iframe> 5 <svg> … </svg> <!-- XHTML/HTML5 Document -- > 6 #el { background-image: url(image.svg); }
  22. 22. SVG Embed Technique Links, External Styles, Interactivity, CSS Animations <img src=”img.svg” alt=”” /> Nope* <object type="image/svg+xml" data="image.svg"></object> Yep <embed type="image/svg+xml" src="image.svg" /> Yep <iframe src="image.svg"></iframe> Yep Inline <svg> … </svg> Yep background-image: url(image.svg); Nope* * CSS animations won’t be played, but SVG (SMIL) animations will be preserved. .
  23. 23. <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="350px" height="400px” viewBox="0 0 350 400" > <style type="text/css"> <![CDATA[ .fish { transform-origin: 50%; animation: shake .4s linear infinite; } @keyframes shake { to {-webkit-transform: rotate(-10deg);} } ]]> </style> <g id="bear" …> <!-- ... --></g> </svg> bear-css.svg Example: CSS Animation
  24. 24. Example (Embedded)
  25. 25. <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="350px" height="400px” viewBox="0 0 350 400" > <g id="bear" …> <!-- … --> <g class=”fish”> <!-- ... --> <animateTransform attributeName="transform" type="rotate" begin="0s" dur=".4s" from="0 380 530" to="-10 380 530" repeatCount="indefinite" fill="freeze" /> </g> </g> </svg> bear-smil.svg Example: SVG (SMIL) Animation
  26. 26. Example (Embedded)
  27. 27. Responsifying SVGs
  28. 28. <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width=”300px height=”300px” > <style type="text/css"> .eye{fill:#8B6A62;} .face{fill:#F6E6E5;} .head{fill:#F7A591;} /* ... */ </style> <path class="body" d=”...”> <!-- ... --> </svg> owl.svg Example
  29. 29. 1. Remove Width & Height, Add viewBox <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 300 300"> <style type="text/css"> /* ... */ </style> <path class="body" d=”...”> <!-- ... --> </svg> owl.svg
  30. 30. 2. Preserve Aspect Ratio <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 300 300" preserveAspectRatio="xMinYMin meet"> <style type="text/css"> /* ... */ </style> <path class="body" d=”...”> <!-- ... --> </svg> owl.svg Note: Without viewBox, preserveAspectRatio has no effect. http://goo.gl/b50HY8
  31. 31. 3. Embed & Wrap in a container <!DOCTYPE html><!-- HTML5 document --> <html> <head> ... </head> <body> <div class=”my-svg-container”> <object type="image/svg+xml" data="owl.svg" class=”my- svg”> <!-- fallback here --> </object> </div> </body> </html> responsive-owl.html SVG can be embedded as <object>, <img> or inline as an <svg>. The technique will work for all three embeds.
  32. 32. 4. Padding Hack on Container .my-svg-container { height: 0; position: relative; /* create positioning context for svg */ width: width-value; padding-top: (SVG height / SVG width) * width-value; } responsive-owl.css For owl.svg: padding-top = 300 / 300 * 100 = 1 * 100 = 100%; If width of container = 60%: padding-top = 300 / 300 * 60 = 1 * 60 = 60%; If owl.svg has width 250px, height 400px: padding-top = 400/250 * 100 = 1.6 * 100 = 160%;
  33. 33. 4. Position SVG Inside Container /* pull the svg to the top of the container */ .my-svg { position: absolute; top: 0; left: 0; width: 100%; /* only required for <img /> */ } responsive-owl.css
  34. 34. 6. Resize!
  35. 35. Animating SVGs with CSS
  36. 36. Transforming SVGs
  37. 37. Initial transform-origin on HTML & SVG Box Model? transform-origin (default value) HTML elements (div, etc.) Yes 50% 50%* SVG elements (circle, rect, etc.) No 0 0** *50% 50% = center of the HTML element itself ** 0 0 is the top left corner of the SVG canvas, not the element itself
  38. 38. CSS Transforms on HTML & SVG <!DOCTYPE html> ... <div style=”width: 100px; height: 100px; background-color: orange”> </div> <svg style=”width: 150px; height: 150px; background-color: #eee”> <rect width="100" height="100" x="25" y="25" fill="orange" /> </svg>
  39. 39. Setting transform-origin on SVG Elements 1. Using Percentage Values: The value is set relative to the element’s bounding box, which includes the stroke used to draw its border. 2. Using absolute length values: The origin is set relative to the SVG canvas.
  40. 40. CSS Transforms on HTML vs SVG (cont’d) <!DOCTYPE html> <style> div, rect { transform-origin: 50% 50%; } </style>
  41. 41. Heads up: Transform-Origin Issue In Firefox With Percentage Values Setting transform-origin using a percentage value currently doesn’t work in Firefox. That is a bug. (It shouldn’t be a problem if you’re not rotating anything.) Setting it in absolute length values should be fairly simple using a graphics editor.
  42. 42. Example: PinWheel PinWheel by http://pixeldoree.com/vector/free-vector-pinwheels-adobe-illustrator-and-png-files/ .wheel { -webkit-transform-origin: 50% 50%; transform-origin: 193px 164px; animation: spin 4s cubic-bezier(.49,.05,.32,1.04) infinite alternate; } @keyframes spin { 50% { transform: rotate(360deg); } }
  43. 43. Zooming out (or in) in Webkit/Blink does not maintain the transform origin at the center of the rotating element. This is a bug. This issue does not happen in Firefox, where the transform origin is set in absolute values (relative to the SVG canvas). Heads up: Transform-Origin Issue In Chrome With Percentage Values
  44. 44. → Just use absolute values (for the time being)!
  45. 45. Heads up: Hardware Acceleration In Chrome CSS 3D transforms are hardware accelerated in Chrome when applied to HTML elements. However, they are not accelerated when used on SVG elements - they have the same performance profile as SVG transform attributes. They are accelerated in Firefox.
  46. 46. Animating SVG Paths
  47. 47. Animated Line Drawing To Animate an SVG path you need to know its exact length. Then: #path { stroke-dasharray: pathLength; stroke-dashoffset: pathLength; /* transition stroke-dashoffset */ transition: stroke-dashoffset 2s linear; } svg:hover #path{ stroke-dashoffset: 0; }
  48. 48. Example #cable { stroke: #FFF2B1; stroke-dasharray: 4000 4000; stroke-dashoffset: 4000; stroke-width: 4; transition: stroke-dashoffset 8s linear; } svg:hover #cable { stroke-dashoffset: 0; } /* turn lamp on */ .inner-lamp{ fill:grey; transition: fill .5s ease-in 6s; } svg:hover .inner-lamp { fill: #FBFFF8; } /* ... */ The animated path is positioned on top of the black path. When SVG is hovered path is animated, and the lamp is “turned on” after path finishes animation, using a delay that is equal to the animation (transition) time of the path.
  49. 49. Example 2 http://goo.gl/zII9p0
  50. 50. var path = document.querySelector('.drawing- path');path.getTotalLength(); //set CSS properties up path.style.strokeDasharray = length + ' ' + length; path.style.strokeDashoffset = length; //set transition up path.style.transition = 'stroke-dashoffset 2s ease-in- out';// animatepath.style.strokeDashoffset = '0'; //more: http://jakearchibald.com/2013/animated-line-drawing-svg/ Animated Line Drawing: Retrieving Path Length Using Javascript
  51. 51. #RecommendedReading http://jakearchibald.com/2013/animated-line-drawing-svg/
  52. 52. Animated Paths (Morphing Paths) http://goo.gl/ri9nwU
  53. 53. Animated Paths (Morphing Paths) The idea is to create a SVG with one path and to morph that path into another one. You’ll need: the first path, the second path, and possibly intermediate paths (depending on your animation). There is no way in CSS to animate one SVG path into another. http://goo.gl/93gFYh
  54. 54. http://snapsvg.io/ Use Snap.svg
  55. 55. “ By using animated SVGs instead of GIFs we were able to reduce our page size from 1.6 mb to 389 kb, and reduce our page load time from 8.75 s to 412 ms. That’s a huge difference.” Animated SVGs As GIFs Replacement http://oak.is/thinking/animated-svgs/
  56. 56. Don’t forget to..
  57. 57. Make SVGs Accessible http://goo.gl/sG7G0j #MustRead
  58. 58. Optimize & Degrade Gracefully http://goo.gl/nhXtbu #MustRead
  59. 59. http://caniuse.com/# search=svg
  60. 60. Thank You! @SaraSoueidan / sarasoueidan.com

×