Do Not be afraid of SVG

Scared Face

Utilize It On Your Web Today

Marek Raida @xrevelon

Scalable Vector Graphics

  • SVG LogoW3C approved standard since 1999
  • focused on 2D vector space
  • vectors = super quality and good performance for every screen resolution
  • HTML5, CSS and JS friendly
  • XML based markup (even when part of HTML5 document!)
  • DOM based with well supported event model
  • nicely supported, even in MSIE 9+ (fallbacks possible)
  • accessible (role attribute, title/desc tags)

How to create SVG

  • manually (just like you do HTML and CSS, man…)
          
  • Palettevector editor like Illustrator or Inkscape
  • online editor like YouiDraw or SVG-Edit
  • download and utilize tons of documents from internet (Google search = filetype:svg)
  • generate it via scripting

PS: And do not forget to serve it as image/svg+xml MIME type

SVG Basics

  • shape primitives: path, line, rect, circle, ellipse, polyline, polygon… Box
  • organization: defs, g, svg, use, a, symbol, image, foreignObject…
  • advanced: marker, pattern, clipPath, mask, gradient, filter…
  • texts: text, tspan, textPath…
  • animations: set, animate, animateTransform, animateMotion  (SMIL) 

viewPort vs viewBox

SVG canvas is infinite. ViewPort is defined by width and height and is internally for percentage sizing use + it gives document's parent (HTML, SVG) its desired dimensions

  <svg width="200" height="200"><!-- content --></svg>

ViewBox is defined by viewBox and defines document's canvas visibility box. Use it a lot, I do! Four values stand for definition of: left top width height frame

  <svg viewBox="-50 -50 200 200"><!-- content --></svg>

No one of them is mandatory, but they are very useful and they can co-exists easily, if you want or need to

  <svg viewBox="-50 -50 200 200" width="100" height="100"><!-- … --></svg>

Integration ways

There are many ways how to integrate SVG in your web project (page). I recommend to stick to these ones:

  1. Puzzleinline svg markup
  2. object tag
  3. image (img) tag
  4. CSS background property
  5. iframe

Inline SVG markup

Mind necessity to keep XML syntax for all SVG markup

 …
 <h2>Some Title</h2>
  <div class="wrapper">
   
   <svg width="80" height="80" xmlns="http://www.w3.org/2000/svg">
     <circle cx="40" cy="40" r="35" fill="orange"/>
     <line x1="0" y1="0" x2="80" y2="50" stroke="green" stroke-width="4"/>
   </svg>
   <script>
     if (!document.implementation.hasFeature(
           "http://www.w3.org/TR/SVG11/feature#Shape", "1.1")) {
       // optional fallback here
     }
   </script>
  </div>
 <p>Text of some paragraph</p>
 …                      

Advantages

  • OKapplicable CSS from embedding document (also currentColor/Shadow DOM support)
  • manipulable via JavaScript
  • no extra file to load
  • accessible

Disadvantages

  • KOnot cacheable
  • cross-browser (MSIE) fluid size trick needed

Fluid design MSIE trick

Use if stretching is needed; fixed size works OK Live demo

    <style>
      .wrapper {
          width: 50%;
          height: 0;
          padding-top: 50%; /* (svg-height / svg-width) * wrapper-width */
          position: relative;
      }
      svg {
          position: absolute;
          top: 0;
          left: 0;
      }
    </style>
    <div class="wrapper">  
      <svg viewBox="0 0 50 50"></svg>
    </div>           

Object tag integration


  …
  <h2>Some Title</h2>

  <object type="image/svg+xml" data="turtle.svg" width="323" height="153">
      
  </object>

  <p>Some paragraph…</p>
    …
                        

Advantages

  • OKapplicable CSS from external stylesheet
  • manipulable via JavaScript (both externally and internally)
  • cacheable, as it is external file
  • intensive pre-compress possible (.svgz)

Disadvantages

  • KOowner document CSS stylesheet not applicable
  • cross-browser (MSIE) fluid size trick needed
  • not directly linkable from HTML (a tag)

Fluid design MSIE trick

Setting width does the trick. Live demo

    <style>
      .wrapper {
          width: 50%;
      }
      .wrapper object {
          width: 100%;
      }
    </style>
    
    <div class="wrapper">  
      <object type="image/svg+xml" data="turtle.svg"></object>
    </div>           

Image tag integration

Good old, familiar and easy way to go…


    <img src="svg/dog.svg" alt="Dog" width="136" height="200"
        onerror="this.onerror=null; this.src='fallback.png'"/>
    <!-- with possible fallback using onerror attribute -->
                        
Dog

Advantages

  • OKcacheable, as it is external file
  • intensive pre-compress possible
  • safe and simple (sandboxed)
  • SMIL is allowed (animated GIF substitute, except for MSIE)

Disadvantages

  • KOexternal (linked) CSS stylesheet not applicable
  • owner document's CSS stylesheet not applicable to individual SVG elements
  • cannot be manipulated via JavaScript (not even internally)
  • interactivity disabled (links, DOM events)

Fluid design MSIE trick

Similar to object tag - you need to set width. Live demo


    <style>
      img {
          width: 100%;
      }
    </style>
    
    <img width="136" height="200" src="svg/dog.svg" alt="Dog"/>
                        

CSS background image

    <style>
      .holder {
        width: 50%;
        height: 50%;
        background: url('img/turtle.png'); /* possible fallback trick */
        background-image: url(svg/fish.svg), none;
        background-size: contain; 
        background-position: center center; 
        background-repeat: no-repeat;
      }
    </style>
    
    <div class="holder"/>
 

Advantages

  • OKno tricks needed for modern browsers
  • cacheable as external file + pre-compressing
  • offers good pre-rendering performance
  • safe and simple (sandboxed)
  • SMIL is allowed (animated GIF substitute, except for MSIE)

Disadvantages

  • external (linked) CSS stylesheet not applicable
  • owner's CSS not applicable to individual elements
  • not manipulable via JavaScript (not even internally)
  • interactivity disabled (links, DOM events)

Internal Media Queries

Embed your media queries inside SVG = put it where it belongs! (OOP Encapsulation, proven practice)


House Icon

HTML vs SVG differences

Arrows There are many SVG only CSS properties and all of them (and more) could be written as direct presentation attributes, but probably the most notable are:

HTMLSVG
borderstroke
color, backgroundfill
border rgba (alpha for opacity)stroke-opacity
background-color rgba (for opacity)fill-opacity
z-indexelement order (planned to SVG2)
background-size: cover/containpreserveAspectRatio = meet/slice

Is CSS drawing good enough?

Example of (not only) Twitter logo recreated in HTML/CSS and crushed to the minimum size (single color image only)

LegendTwitterLock
HTML+CSS
GZipped
2.9 kB
1.4 kB
impossible
to do ????
SVG
GZipped
1.2 kB
0.6 kB
24.7 kB
6.4 kB
PNG
crunched
4.1 kB
1.4 kB
124.7 kB
31.9 kB
Twitter Logo         Lock Image

Sharing CSS definitions

Inline code case, notice symbol element use.

<style> span { color: darkgreen; fill: currentColor; } </style>
<span>My cute jellyfish
  <svg stroke="none" width="60" height="60">
    <symbol id="jellyfish" viewBox="0 0 400 500">
      <path d="M200,0.438c-90,0.772-172,72-192,160-6.89,28-8.74,57…
      <g id="eye" transform="matrix(0.89472818,0,0,0.89472818,363.45969…
        <path fill="yellow" d="m-139,494c-4.15,39.8,46.2,71.1,80.1…
        <path fill="black" d="m-112,494c-4.57,20,18.9,32.5,35.7,26.2,12.5…
      </g>
      <use xlink:href="#eye" transform="translate(-150 0)"/>
    </symbol>
    <use xlink:href="#jellyfish"/>
  </svg>
</span>
<span>Another cute jellyfish
  <svg><use xlink:href="#jellyfish"/></svg>
</span>              
My cute jellyfish Another cute jellyfish

External CSS & object

/* objectcase.css file */ 
span, use#jellyfishExt { color: magenta; fill: magenta; }
<style type="text/css"> 
  @import url(css/objectcase.css);
</style>
<span>My shared jellyfish
  <object type="image/svg+xml" data="jellyfish.svg" width="60" height="60"/>
</span>              
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink">
  <style type="text/css">
    @import url(css/objectcase.css);
  </style>
  <!-- I prefer this CSS linking instead of <?xml-stylesheet… ?> way -->
  <symbol id="jellyfish" viewBox="0 0 400 500">
    …rest of the symbol definition…
  </symbol>
  <use xlink:href="#jellyfish" id="jellyfishExt"/>
</svg>               
My shared jellyfish

External Sprites I.

<svg xmlns="http://www.w3.org/2000/svg">
   <symbol viewBox="0 0 800 1313" id="r2d2">
      <path d="M10.965784,-230.08768L54.388126,-413.23943L161.54509…">…
   </symbol>
   <symbol viewBox="0 0 200 222" id="darth">…</symbol>
</svg>
<h3>Smart R2D2</h3>
<svg>
   <use xlink:href="svg/sprites.svg#r2d2"/>
</svg>
<h3>Darth Minnie</h3>
<svg>
   <use xlink:href="svg/sprites.svg#darth"/>
</svg>
External link  

External Sprites II.

Use of view with identifier is another very popular way.

<svg xmlns="http://www.w3.org/2000/svg">
   <view viewBox="0 0 800 1313" id="r2d2"/>
   <path d="M10.965784,-230.08768L54.388126,-413.23943L161.54509…">…

   <view viewBox="900 900 200 222" id="darth"/>
</svg>
<h3>Smart R2D2</h3>
<img src="svg/sprites2.svg#r2d2"/>

<h3>Darth Minnie</h3>
<img src="svg/sprites2.svg#darth"/>
</svg>
External link  

JS manipulations

<input onchange="document.getElementById('txt').firstChild.data=this.value">

<svg width="310" height="120">
  <path id="crc" stroke="none" fill="none" d="M50,0c0,27.6-22.4,50-50,50s-50-22.4-50-50,22.4-50,50-50,50,22.4,50,50z"/>
  <g transform="translate(150 60) scale(2 0.8)">
    <text font-size="26px" font-family="sans-serif" fill="green">
      <textPath xlink:href="#crc" id="txt">Text Writ Around The Circle</textPath>
      <animateTransform attributeName="transform" type="rotate" from="0" to="360" begin="click" repeatCount="1" dur="9s"/>
    </text>
  </g>
</svg>           
Text Writ Around The Circle

Understanding path

Substitutes every other shape. Some available commands:

  • M = Move To X,Y (applied from current position)
  • L = Line To X,Y (the same for all commands…)
  • C = Cubic Bézier To x1,y1 x2,y2 X,Y
  • Z = Close Path (to the starting point, exception ;-)

Notice two Control Points in curve command.


<path d=""/>
Tester Testakovitch Testakoff Tester Testakovitch Testakoff Tester Testakovitch Testakoff Tester Testakovitch Testakoff Tester Testakovitch Testakoff Tester Testakovitch Testakoff

Line Drawing - script

MSIE compatible solution, DOM manipulation involved.

  <svg>
    <path id="drawMe" d="M 246,188 l3,12h2l5-6c0,4,1,6,5,7,3-5,8-2…"/>
    <script>
      var lineElem = document.getElementById("drawMe");
      var lineLength = elem.getTotalLength();
      lineElem.style.strokeDasharray = lineLength; // +' '+ lineLength
      lineElem.style.strokeDashoffset = lineLength;
      // animation cycle follows
      window.requestAnimationFrame(…shift strokeDashoffset here…);
    </script>
  <svg>              
External link  

Line Drawing - SMIL

Synchronized Multimedia Integration Language solution.

  <svg>
    <path stroke-dasharray="1439" stroke-dashoffset="1439" d="M 246,188…">
      <animate attributeName="stroke-dashoffset" from="1439" to="0" 
        dur="4s" repeatCount="1" fill="freeze"/>
    </path>
  <svg>              
External link  

Line Drawing - CSS

Don't forget to add necessary prefixes (like -webkit-…)

 <svg>
   <style>
     .animate {
       animation: draw 4s linear 1 forwards;
     }
     @keyframes draw {
       100% {
         stroke-dashoffset: 0;
       }
     }
   </style>
   <path stroke-dasharray="1439" stroke-dashoffset="1439" d="M 246,188…"/>
 <svg>              
External link  

Line Drawing - GSAP

Does not work with standalone SVG documents
and is somewhat commercial

<html>
 <head/>
 <body>
   <script src="http://https://cdnjs.cloudflare… …TweenMax.min.js"></script>
   <svg>
     <path stroke-dasharray="1439" stroke-dashoffset="1439" d="M 246,188…"/>
   </svg>
   <script> TweenLite.to('path', 4, {strokeDashoffset:0}); </script>
 <body>
<html>              
External link  

Use reflections

use tag creates live reflection of any existing node. It not only saves lines of code, but can do true miracles!!

Two Mirrors
  <g id="complexElementID" class="…">
    <circle …/> <rect …/> <text …/> <path id="somePathID" …/>
  </g>
  <use xlink:href="#complexElementID" transform="scale(2)" class="c1…"/>
  <g class="whatever">
    <use xlink:href="#complexElementID" transform="scale(5)" class="c2…"/>
    <use xlink:href="#somePathID" transform="rotate(180)" class="c3…"/>
  </g>           

References are using xlink:href="#refID" syntax.

Best SVG utilization

You know it already, I know, but just to be sure ;-)

  1. maps of countries, regions even world
  2. Awardgraphs, diagrams and data visualizations
  3. technical plans and drawings
  4. interactive infographics
  5. colorful icons, superior to icon fonts
  6. and off course - responsive images ;-)

Pumpkin Carving

<mask id="myMask"/>
<g id="pumpkin">…several paths there…</g>
<script>
  var carving;
  pumpkin.onmousedown = function(evt) {
    carving = document.createElement('path');
    myMask.appendChild(carving);
  }
  pumpkin.onmousemove = function(evt) {
    carving.setAttribute('d', carving.getAttribute('d') + 
      " " + evt.clientX + " " + evt.clientY);
  }                 
External link

Website logo story

Shape Morphing


  <path    d="M5,5 L10,10 15,20 50,33…>
    <animate attributeName="d" dur="10s" start="0s" repeatCount="indefinite"
      values="M15,10 L5,5 17,30 7,20…;
              M15,10 L2,2 70,11 8,42…" />
  </path> (Batman Logo Evolution by Tavmjong Bah, M$ incompatible)
                 
External link

Limitations (= M$)

MSIE/Edge doesn't support CSS Transformations to SVG content, so direct tag attributes have to be used.

KOMSIE also doesn't support CSS Transitions and Animations of otherwise supported SVG related CSS properties - latest Edge does?, which leaves us with reasonable utilization of only one property: opacity.

They are also the only browsers not supporting SMIL Animation, so putting SVG in motion is not so easy.

Scripting and tools could solve these issues, but it's a pity.

My recommendations

Following exceptional and wise people and sophisticated tools are great to learn from or definitely worth trying:

Do not worry about

  1. MSIE 8 and lower are declining rapidly, having share from 1.5% to 12% respectively
  2. Trendsdesktop browsers are declining anyway and all major mobile ones render SVG more than well
  3. elder Android versions without SVG, like Gingerbread are dying even faster
  4. performance, as long as you do not have SVG documents with thousands of complex paths, is good
  5. it's a living standard, evolving and used more and more

Bits of the Future

Learn it and love it, SVG will not let you down!

THE END?

Thank you!

Thank you!