Mastering SVG

5 (2 reviews total)
By Rob Larsen
    Advance your knowledge in tech with a Packt subscription

  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Introducing Scalable Vector Graphics

About this book

SVG is the most powerful image format in use on the web. In addition to producing resolution-independent images for today's multi-device world, SVG allows you to create animations and visualizations to add to your sites and applications. The simplicity of cross-platform markup, mixed with familiar modern web languages, such as CSS and JavaScript, creates a winning combination for designers and developers alike.

In this book, you will learn how to author an SVG document using common SVG features, such as elements and attributes, and serve SVG on the web using simple configuration tips for common web servers. You will also use SVG elements and images in HTML documents.
Further, you will use SVG images for a variety of common tasks, such as manipulating SVG elements, adding animations using CSS, mastering the basic JavaScript SVG (API) using Document Object Model (DOM) methods, and interfacing SVG with common libraries and frameworks, such as React, jQuery, and Angular.

You will then build an understanding of the Snap.svg and SVG.js APIs, along with the basics of D3, and take a look at how to implement interesting visualizations using the library. By the end of the book, you will have mastered creating animations with SVG.

Publication date:
September 2018
Publisher
Packt
Pages
312
ISBN
9781788626743

 

Chapter 1. Introducing Scalable Vector Graphics

Scalable Vector Graphics (SVG) is one of the most powerful components of modern web development. If used properly, it can solve common problems relating to the design, development, and delivery of imagery and user interfaces

SVG is an XML-based markup language used to define images. What HTML is to text, SVG is to images.

SVG is very flexible. It can be implemented as a standalone image and used as the src of an image or as a background image in CSS such as a PNG, GIF, or JPG. It can also be embedded directly into an HTML page and manipulated with CSS or JavaScript to create animations, visualizations, and interactive charts.

So, if SVG is that important and can do so much, why isn't it even more widely used? Why does it feel like we're only scratching the surface of what's possible with it? Why does it still feel like a newthing? 

The problem is, not everyone knows everything that SVG is capable of and not everyone who knows what it's capable of is able to implement SVG solutions in an optimal manner. This book aims to help everyone interested in using SVG to get over those hurdles and master this vital technology.

SVG has had a circuitous route to its place in the pantheon of modern web development technologies. Released in 1999 (it's older than XHTML), SVG languished for a decade because of lack of support in the then dominant Internet Explorer browsers. The technology started to gain favor several years ago with JavaScript libraries, such as Raphaël, which added programmatic fallback support for older versions of IE and the trend has only grown stronger since. Thankfully, the tide has fully turned. All modern versions of Internet Explorer and Edge have support for SVG and there's strong support for the technology from all browser manufacturers, including, of course, Chrome and Firefox.

By the end of this chapter, you will understand the basics of SVG in its many guises. You will be able to take existing SVG images and use them in web pages and CSS with confidence and you'll be well on your way to the promised land of SVG mastery.

This chapter will cover the following topics:

  • An introduction to fundamental SVG grammar and vector graphics in general
  • The whys and hows of using SVG as thesrc file of an image
  • Basic usage of SVG as a CSS background image
  • The benefits and differences of using SVG embedded directly in a document
  • A brief introduction to Modernizr and feature detection
 

Creating a simple SVG image


If you're at all familiar with HTML, then the basics of an SVG document are going to be familiar to you. So let's get the mystery out of the way early and take a look at a simple SVG document. 

The following code sample shows the basic structure of SVG. The first element is the standard xml declaration, indicating that the following should be parsed as an XML document. The second element is where the fun begins. It defines the root SVG element (in the same way that there's a root HTML element in an HTML document). height and width define the intrinsic dimensions of the document. The XML NameSpace (xmlns) is a reference to the schema that defines the current XML element. You'll learn about viewBox in more detail in the next chapter. There are many other attributes possible on an SVG element. You will learn more about them throughout this book.

In this first example, following the SVG element, there's a single SVG text element. The text element, like the SVG element, has many possible attributes that you'll learn about as you make your way through the book. In this case, there are four attributes related to the display of the element. The x and y attributes represent the position of the top-left corner of the text element as points on a coordinate plane. font-family maps to the familiar CSS property of the same name and defines the specific font that should be used to display the text. font-size also maps to the common CSS property of the same name.

Note

The attributes that accept length values (in this example width, height, and font-size) are provided without a unit (for example, px, em, and %.) When these values are presented as attributes, the unit is optional. If no unit is provided, the values are specified as being user units in the user space. You'll learn more about the way that values are calculated in SVG throughout the book. For now, just remember that, in practice, user units will be equivalent to pixels.   

Finally, there is the content of the text element, the simple message Hello SVG:

<?xml version="1.0" encoding="UTF-8"?>
<svg width="250" height="100" viewBox="0 0 250 100" version="1.1" xmlns=”http://www.w3.org/2000/svg”>
<text x="0" y="50" font-family="Verdana" font-size="50">
    Hello SVG
  </text>
</svg>

Saved as 1-1-hello-world.svg and opened in a browser, the previous markup renders as in the following screenshot:

Now that you've seen the most basic example of an SVG document, let's take a look at the basic usage of SVG images and elements in a variety of ways.

 

Using SVG as a content image


In this section, you'll learn about the single most basic usage of an SVG image, using it the same way you would use a JPG, PNG, or GIF, as the src of an img element. If you've done any work with HTML at all then you will know how to do this since it's just an image element, but you should start to think about all the different ways you can use SVG, and this is a big one.

Looking at the following code sample, there's nothing special at all about the img element. There's an src pointing to the SVG image, height and width to define the image's dimensions, and an alt attribute to provide a textual representation of the image for screen readers and other cases where the image may not display:

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Mastering SVG - Inserting an SVG Image into an HTML
         Document</title>
    </head>
    <body>
      <img src="1-2-circles.svg" width="250" height="250" alt="an image
        showing four circles lined up diagonally across the screen">
    </body>
</html>

Running the preceding code in a browser renders the following:

Note

One thing that might be a slight problem is that not all web servers, by default, set the correct MIME type for SVG. If the MIME type is set incorrectly, some browsers will not display the SVG image correctly. As one common example, Microsoft's IIS may need a specific configuration setting changed (https://docs.microsoft.com/en-us/iis/manage/managing-your-configuration-settings/adding-ie-9-mime-types-to-iis) to properly serve SVG images. The correct MIME type is image/svg+xml.

 

Drawing with code


Before you learn about other basic implementations, it's worth taking a look at the previous screenshot in a little more depth. Instead of just being text like the first example (which, after all, you could have just done in HTML), it shows four circles diagonally arranged across the canvas. Let's take a look at the source of that image and learn our first visual element in SVG, the circle element.

The following code sample shows the circle in action. It also shows how simple changes in markup attribute values can create visually interesting patterns. In it there are five circle elements. These all take advantage of four new attributes. cx and cy represent the center x and center y coordinates of the element on a coordinate plane. r represents the radius of the circle. fill defines the color that will fill the circle. fill accepts any valid CSS color value (https://developer.mozilla.org/en-US/docs/Web/CSS/color_value). In this case, we're using a red,green, blue, alpha (RGBA) value to fill this with variations on pure red. The first few values remain the same while the fourth value, the alpha, doubles every time from .125 to 1 (fully opaque). Similarly, cx, cy, and r double each time. This produces the pattern you saw earlier. This isn't the most elaborate SVG image, but it does show you how easy basic SVG elements are to use and understand: 

<?xml version="1.0" encoding="UTF-8"?>
<svg width="250" height="250" viewBox="0 0 250 250" version="1.1" xmlns="http://www.w3.org/2000/svg">
       <circle cx="12.5" cy="12.5" r="6.25" fill="rgba(255,0,0,.125)">
       </circle>
       <circle cx="25" cy="25" r="12.5" fill="rgba(255,0,0,.25)">
       </circle>
       <circle cx="50" cy="50" r="25" fill="rgba(255,0,0,.5)"></circle>
       <circle cx="100" cy="100" r="50" fill="rgba(255,0,0,.75)">
       </circle>
       <circle cx="200" cy="200" r="100" fill="rgba(255,0,0,1)">
       </circle>
</svg>

Scalable + vector graphics

Now that you've seen an example of a drawing created with SVG, it might be useful to take a second to explain the VG in SVG and why that makes the file format scalable

With raster (bitmap) file formats, you're probably familiar with formats such as JPG, PNG, or GIF. You can think of the image data as being stored pixel by pixel, so each point in an image is stored in the file and read out by the browser or graphics program pixel by pixel and row by row. The size and quality of the image is constrained by the size and quality at the time of creation. 

 

 

Note

There are optimizations for all the bitmapped file formats that limit the actual amount of data stored. For example, GIFs use the LZ77 algorithm to collapse redundant pixels down to a backpointer and reference pixel. Imagine if your image has 100 pixels of pure black in a row. The algorithm will search through the image for a sequence of same-bytes and when a sequence is encountered, the algorithm will search backwards through the document to find the first instance of that pattern. It will then replace all those pixels with instructions (a backpointer) on how many characters back to search and how many pixels to copy to fill in the number of same-bytes. In this case, it would be 100 (pixels to search) and 1 (pixels to copy).

Vector graphics, on the other hand, are defined by vectors and control points. To simplify significantly, you can think of vector graphics as being a set of numbers that describe the shape of a line. They may be a set of specific points or they may be, as in the case of the circle earlier, a set of instructions on how to create a specific type of object. The circle element doesn't store every pixel that makes up the circle. It stores the arguments used to create the circle.

Why is this cool? One reason is that because it's just a set of instructions defining the shape, which you can scale in or out, and the rendering engine will just calculate new values accordingly. For that reason, vector graphics can scale infinitely without loss of fidelity.

If that's all confusing to you, don't worry about it. The more you work with them, the more familiar you'll be with the way vector graphics work. In the meantime, the following set of examples and figures will help to illustrate the difference. First, look at the following markup. It represents four images, using the exact same SVG image as the source. The image represents the SVG logo. The dimensions are set at the image's natural size and then 2x, 4x, and 8x, the image's natural size:

      <img src="svg-logo-h.svg" width="195" height="82" alt="The SVG 
       logo at natural dimensions">
      <img src="svg-logo-h.svg" width="390" height="164" alt="The SVG 
       logo 2x">
      <img src="svg-logo-h.svg" width="780" height="328" alt="The SVG
       logo 4x">
      <img src="svg-logo-h.svg" width="1560" height="656" alt="The SVG
       logo 8x">

 Rendered in the browser, that markup produces the following. Notice that it's completely crisp all the way up to 8x, the original size:

Now, look at the same markup, this time with PNGs. It follows the same pattern:

      <img src="svg-logo-h.png" width="195" height="82" alt="The SVG
       logo at 'natural' dimensions">
      <img src="svg-logo-h.png" width="390" height="164" alt="The SVG 
       logo 2x">
      <img src="svg-logo-h.png" width="780" height="328" alt="The SVG
       logo 4x">
      <img src="svg-logo-h.png" width="1560" height="656" alt="The SVG
       logo 8x">

But now, see the result. Notice that, at the natural level, there is no difference between the SVG and PNG. The pixels in the PNG are enough to match the vector-defined lines in the SVG Version. Also, notice how the image gets progressively worse as the image gets larger. There is no way for the browser to get more information (more pixels) out of the bitmapped format to fill in the details at the larger size. It simply scales up the pixels that it has, with terribleresults (especially at the 8x level):

 

 

Using SVG in CSS


A common usage of SVG is as a background image in CSS. There are benefits to this approach in terms of file size and scalability in responsive web design (RWD). In today's multi-device, multi-form factor world, the ability to offer high-quality images at a range of device sizes and resolutions (including high pixel density devices) is an important one. While there are optimized solutions for raster display images (in the form of the picture element and the srcset and sizes attributes) and you can use media queries to present different images or image sizes in CSS, the ability to do one image for all devices is huge. SVG in CSS allows us to do that easily

While you'll learn about the intersection of SVG and CSS in Chapter 5, Working with SVG and CSS, let's take a look at a basic example now to whet your appetite.

The following page has a div tag with a class of header. The only thing to really note here is a reference to an SVG file in the url value of the background property:

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Mastering SVG- Using SVG images in CSS</title>
        <style type="text/css">
            .header {
                color: #ffffff;
                background: url(1-3-gradient.svg) repeat-x;
                width: 500px;
                height: 40px;
                text-align: center;
            }
        </style>
    </head>
    <body>
      <div class="header"><h1>CSS!</h1></div>
    </body>
</html>

This code produces the following when run in a browser. This simple example, which is no different than any other CSS implementation, will scale to the highest points-per-inch display without any loss of smoothness in the gradient. This is achieved simply by using SVG:  

Gradients in SVG

As you continue to learn about basic SVG usage, I'm going to continue to tease new concepts in authoring SVG itself. The next features I'm going to introduce you to will be the definitions (defs) section, the gradient element, and the rect element.

The following example shows the source of the SVG element in the previous example. Everything beyond the root svg element itself is different to the previous example.

First up, there's the defs element. defs is an organizational element designed to hold definitions of graphical objects to be used later in the document. We immediately meet the linearGradient element, which defines (you guessed it!) a linear gradient. x1, x2, y1, and y2 define the gradient vector of the gradient. You'll learn more about that in Chapter 2, Working with SVG and CSS, but for now, just know that it defines the direction of the gradients. The default is 0 at the left and 1 to the right. Setting x2 to 0 and y2 to 1 changes the angle from a horizontal left-to-right gradient to a vertical top-to-bottom gradient. 

The look of the gradient is actually defined as child stop elements. Each has two attributes, offset and stop-color. The offset accepts either a percentage or a number between 0 and 1, representing the placement of the gradient stop on the totality of the gradient vector. This example is the simplest: one color at 0% and another at 100%. stop-color accepts any valid color value:

<svg width="10" height="40" viewBox="0 0 10 40" version="1.1" xmlns="http://www.w3.org/2000/svg">
 <defs>
 <linearGradient id="gradient" x1="0" x2="0" y1="0" y2="1">
 <stop offset="0%" stop-color="#999999"/>
 <stop offset="100%" stop-color="#000000"/>
 </linearGradient>
 </defs>
 <rect x="0" y="0" width="10" height="40" fill="url(#gradient)"/>
</svg>

As these are just instructions on how to render the gradient, it's possible to stretch and shift the background image in this case with zero loss of fidelity. The browser will just calculate new values and render a new, perfect gradient.

The following example shows a tweak to the CSS that stretches the header to be half of the height of the browser (using the vh unit) and forces the header background image to fill the available space (background: size: contain):

<!doctype html>
<html lang="en">
 <head>
   <meta charset="utf-8">
   <title>Mastering SVG- Using SVG images in CSS</title>
   <style type="text/css">
  .header {
   color: #ffffff;
   background: url(1-3-gradient.svg) repeat-x;
   width: 500px;
   height: 50vh;
   text-align: center;
   background-size: contain;
  }
  </style>
 </head>
 <body>
   <div class="header"><h1>CSS!</h1></div>
 </body>
</html>

As you can see in the following screenshot, the same background image handles the resizing with flying colors. This is true (as you'll learn) for anything else you can do with SVG.

 

Directly embedding SVG in an HTML document


In my opinion, the most exciting usage of SVG is as an inline element in an HTML document. While you will learn about SVG images as a separate file format and all the ways that SVG images can be used to develop modern web apps, the largest portion of this book will show you ways to interact with SVG elements embedded directly into the document. This is important because it is not possible to animate or otherwise manipulate the individual elements of an externally-referenced SVG file; this is only possible if the SVG elements are available directly (via the Document Object Model (DOM)) on the page.

The following example shows a simple inline SVG image with three circles and teases one of the most powerful tools you have when working with inline SVG: CSS! CSS can be used to style SVG elements in the same way that you can style regular HTML elements. This opens up a world of possibilities. The properties used here are probably new to you since they are SVG-specific, but just like the background-color or border properties you're used to, you can adjust the basic look and feel of SVG elements with CSS. In this next example, the CSS defines a default fill color for all circles, adds a border to the second circle, and then changes the fill color for the third circle. If you're not already scheming of ways to use CSS to manipulate SVG elements, rest assured you'll have plenty of ideas after reading Chapter 5, Working with SVG and CSS:

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Mastering SVG - Using SVG images in CSS</title>
        <style type="text/css">
            circle {
              fill: rgba(255,0,0,1);
            }
            .first {
              opacity: .5;
            }
            .second {
              stroke-width: 3px;
              stroke: #000000;
            }
            .third {
              fill: rgba(0,255,0,.75);
            }
        </style>
    </head>
    <body>
      <svg width="400" height="250" viewBox="0 0 400 250" version="1.1"
       xmlns="http://www.w3.org/2000/svg">
        <circle cx="100" cy="100" r="25" class="first"></circle>
        <circle cx="200" cy="100" r="25" class="second"></circle>
        <circle cx="300" cy="100" r="25" class="third"></circle>
        </svg>
    </body>
</html>

Opening a browser will show the results of all that CSS:

 

Feature detection and Modernizr


While overall support for SVG on the global web (https://caniuse.com/#search=svg) is now very high, it's not uniform and there are still non-supporting browsers out there. This is where Modernizr, the feature detection library, can be useful. If your user base is broad or you're using newer (even experimental) features, you can use Modernizr to detect browser compatibility with your important features and adjust your code accordingly.

There are two ways this works. One is the classes that Modernizr can place on the HTML element. The other is the global Modernizr object that contains results for all the tests as Booleans. Before we move on, I'll show you examples of both tools in action.

The Modernizr project provides hundreds of tests. Since some of the tests are quite expensive (in terms of resources needed to compute, when working with Modernizr, you want to use just the tests you need for your application. In this case, I've created a specific build of Modernizr that tests for multiple SVG features and nothing else. When added to an HTML page, this file will add classes to the HTML element indicating support for various SVG features

 

Here's the output of the HTML element in Microsoft Edge. The no-smil class indicates that Edge doesn't support Synchronized Multimedia Integration Language (SMIL), but does support everything else we're testing for:

<html class=" svg svgclippaths svgforeignobject svgfilters
 no-smil inlinesvg svgasimg" lang="en">

Output from the latest Chrome Version indicates support for all tested features:

<htmlclass=" svg svgclippaths svgforeignobject svgfilters smil 
 inlinesvg svgasimg" lang="en" >

And finally, Internet Explorer 8 (IE8), which has no SVG support at all:

<HTML class=" no-svg no-svgclippaths no-svgforeignobject no-svgfilters 
 no-smil no-inlinesvg no-svgasimg" lang="en">

Using these classes would allow you to, as a simple example, provide a PNG fallback function for CSS background images in IE8:

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Mastering SVG- Modernizr</title>
        <style type="text/css">
            .header {
                color: #ffffff;
                background: url(1-3-gradient.svg) repeat-x;
                width: 500px;
                height: 40px;
                text-align: center;
            }
            .no-svg .header {
                background: url(1-3-gradient.png) repeat-x;
              }
        </style>
    </head>
    <body>
      <div class="header"><h1>CSS!</h1></div>
    </body>
</html>

As was mentioned, Modernizr also exposes a global Modernizr JavaScript object with each of the tests available as a Boolean. The following example shows how to access that Boolean and using an if statement for the code approximately, depending on whether or not SVG is supported:

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Mastering SVG- Monderizr JavaScript Object</title>
        <script src="modernizr-custom.js"></script>
      </head>
    <body>
      <script>
        if (Modernizr.svg){
          // do things with SVG
        } else {
          //create a non-SVG fallback
        }
      </script>
    </body>
</html>

In general, the rest of this book will not focus on fallbacks for older browsers, but it is useful to know that they're available if you're working in an environment where you need to support a broad range of browsers and devices.

 

 

Summary


In this chapter, we learned about the basics of SVG including several SVG-specific elements, such as circle, text, and the elements used to make SVG gradients. We also learned about several ways to use SVG in HTML documents and as a background image in CSS.

We also learned about the Modernizr feature detection library and how to use it to create fallbacks for browsers that don't support SVG or specific SVG features.

In Chapter 2Getting Started with Authoring SVG, you'll learn about many more SVG features as you will expand your knowledge of authoring SVG documents.

About the Author

  • Rob Larsen

    Rob Larsen is an experienced frontend engineer, team lead, and manager. He is an active writer and speaker on web technology with a special focus on the continuing evolution of HTML, CSS, and JavaScript.

    He is a co-author of Professional jQuery, the author of Beginning HTML and CSS, and the author of The Uncertain Web. He's also an active member of the open source community as a maintainer of several popular projects

    Browse publications by this author

Latest Reviews

(2 reviews total)
Excelente material para aprender SVG
То, что нужно. Давно ждал подобной книги на packt.

Recommended For You

Mastering SVG
Unlock this book and the full library for FREE
Start free trial