© Alex Libby  2018
Alex LibbyBeginning SVGhttps://doi.org/10.1007/978-1-4842-3760-1_3

3. Working with Images and Text

Alex Libby1 
(1)
Rugby, Warwickshire, UK
 

One of the key benefits of working with SVG is the ability to resize an image with no loss of quality – to achieve this, we can use any one of several different core shapes (such as squares or circles), or even go freehand with paths, to create our design.

This is ideal for those instances where we can draw a relatively straightforward image – what if we needed to work with something more complex? This does not mean to say that SVG is limited to simple designs at all: other designers have produced some really complex SVG work, which includes animation, filters, transitions, and the like!

It does raise the question though as to what we can (or should) do if we need to work with standard images (i.e., not SVG). Can we include them in an SVG…? Would that even work…? Well, you can – let’s dive in and take a look in more detail, starting with a recap on inserting images.

Inserting Images

Images – a vital part of any site; it goes without saying that a website without some form of visual content will clearly suffer. For example – images of products in an online store: customers will vote with their feet if they are anything less than perfect!

It goes without saying that we would use tried and tested code such as <img src="...."> to add the image to a page; if we enter the world of SVG, this opens up some extra possibilities. Take for example this image of a close-up of one of my favorite plants, a moth orchid, as shown in Figure 3-1.
../images/461821_1_En_3_Chapter/461821_1_En_3_Fig1_HTML.jpg
Figure 3-1

A Phaelenopsis orchid – Source: Flickr/pagonzales

At first glance, it looks a perfectly ordinary image, right? It’s a great shot of an orchid, close up; it has a title that’s been added to confirm what type of orchid is in the image. What if I said this was a screenshot of an SVG element…and not a standard PNG or JPEG image?

No – I’ve not lost my marbles: Figure 3-1 is indeed an SVG image; to see it in action, try previewing the embedimage.html file in a browser from the code download that accompanies this book. How did we achieve this? Let’s take a look at the code:
<svg viewbox="0 0 500 500">
   <rect x="10" y="10" height="500" width="500" style="fill: #000000"/>
   <image x="20" y="20" width="94%" height="94%" href="img/orchid.jpg" />
   <text x="23" y="75" font-family="Verdana" font-size="35" stroke="#ffffff" fill="#CC46BF">Phaelenopsis orchid</text>
   <line x1="20" y1="80" x2="440" y2="80" style="stroke: #ffffff; stroke-width: 3;"/>
  </svg>

We have a standard SVG element, set with a 500px square viewbox area – inside this we fill it with a black rectangle. The core of the code lies in the <image> element – this is set to start 20px in and to the right of point zero, and covers 94% of the rectangle (to provide the border effect). We then add a <text> element, which includes the name of the orchid; this is underlined by use of a <line> element that stretches across most of the image.

Understanding the Benefits

At this point I’m sure you will be asking one particular question – how would this work better than a simple PNG or JPEG (or even WebP) format image? Well, there are several benefits from using this approach:
  • The SVG image can be made scalable without loss of quality – the downside is that our embedded image must be made large enough to suit the environment, so care needs to be taken over resource usage;

  • We can add in text, which can be crawled for SEO purposes;

  • If the SVG element is inline, then we can manipulate its contents using standard CSS and jQuery;

  • If needed, we can export a fallback image automatically, for those browsers that don’t support SVG – it has to be said though that they should have been put out to pasture a long time ago (yes, I’m looking at you, IE!).

Now – inserting images into SVG elements is just part of what we can achieve; there is a host of other tricks we can use, including embedding objects such as video! This opens up some interesting possibilities, but before we explore them, there is one topic we should cover: image fallback. Most modern browsers support SVG by default, but as in life, there always has to be the odd one out that people are still using…

Exporting Images

At this point, we’ve created some SVG images using the shapes we covered back in Chapter 2 – our design looks great, and can now be added to our page. Surely that’s the next step…right?

Well, in some cases the answer may be no – there is one more step we should explore first: Do we need to support older browsers, such as IE8…? It’s at this point we need to make that decision – according to the W3Counter website ( https://www.w3counter.com/trends ), there is a minority of users who are still using this browser. Irrespective of the reasons for not wanting or being able to update, it is nevertheless a group of users who we may need to cater for!

Leaving aside the reasons, let’s assume for whatever reason that we need to provide this support. To take out some of the pain of providing this support manually (which doesn’t add any value to the process), we can consider automating it; this is something that can be left to run in the background, allowing us to concentrate on more important tasks. It’s an easy process to set up, but will come in two parts – let’s dive in and take a look.

AUTOMATING EXPORT OF SVG IMAGES

This next exercise requires the use of Node.js and the svg2png NPM package (available from https://www.npmjs.com/package/svg2png ). For now, we will use it in a basic capacity, but it does raise some interesting questions that may determine how you provide support. Let’s take a look first at the technical steps:

Please note – the instructions will be for Windows (as this is the author’s normal development platform). If you are a Mac or Linux user, there are plenty of articles online that will take you through the installation process, such as the one at https://openclassrooms.com/courses/ultra-fast-applications-using-node-js/installing-node-js .

  1. 1.

    First, we need some SVG images to work on – go ahead and extract a copy of the img folder from the export folder in the code download that accompanies this book. Inside this folder are some simple SVG images of credit card / payment methods.

     
  2. 2.

    We need to download and install Node.js, which is available from https://nodejs.org  – for the purposes of this exercise, accept all defaults. Fire up Node.js command prompt as administrator.

     
  3. 3.

    In the Node.js command prompt window, change the working directory to our project folder, by entering cd svgbook and pressing Enter. (If your project directory uses a different name, then please adjust to suit.)

     
  4. 4.

    At the prompt, enter this command then press Enter: svg2png img/visa.svg -h=681 -w=974

     
  5. 5.

    Verify that the image has been created (Figure 3-2) and can be opened using image viewer or in browser (it will appear at the root of our project folder).

     
../images/461821_1_En_3_Chapter/461821_1_En_3_Fig2_HTML.jpg
Figure 3-2

SVG image exported in PNG format

Exporting Images – an Epilogue

Perfect – we have a process in place to create our PNG fallback images: we can move onto more important tasks….

Not so fast my dear reader – can you spot a major flaw in our design? It’s a deliberate gap – our process can only handle one image at a time, when run using the command line. This is fine if we’re working on one image, but we may have hundreds – clearly this isn’t something sustainable!

Thankfully the svg2png package can be used within a task runner such as Grunt ( http://gruntjs.com ), or Gulp ( https://gulpjs.org/ ), to help automate the process if desired – I’ve focused more on the principles of conversion for this exercise, but if you browse to the NPM site, you will find details of how to implement the code required to fully automate conversion of images.

It should be said though that providing a fallback must be a considered decision: Is it worth spending time implementing this process if our target market only includes a tiny proportion of browsers that don’t support SVG? If we don’t provide PNG images, then what are the alternatives? It might be that we create a font that stores SVG icons for example (more anon), or that we convert images to data-URIs and store these in our style sheets. I would strongly recommend spending some time researching the options on the NPM package directory at https://www.npmjs.com  – it’s possible that you might find a package that provides a solution that better fits your needs!

For example, have a look at https://www.npmjs.com/package/svg-to-png  – it’s an older package that hasn’t been updated for a while and doesn’t provide command-line support; this may work just as well as svg2png.

One option we can explore though as part of exporting is to use data-URIs – these convert any images (including SVG) to long strings of random characters that can be inserted into our style sheet, as a replacement for calling a separate image. There are some benefits to using this process, so without further ado, let’s dive in and take a look at the process in more detail.

Using SVGs as Data URIs

Do you remember the “Adding a Pattern” demo we created back in Chapter 2? We touched on the use of data-URIs, where we can convert images to seemingly random strings of characters, which can be set against a background-image property within our style sheet.

Well, it’s worth revisiting this subject – if you take a close look at the code, you will see this within the body style rule:
background-image: url("data:image/svg+xml,%3Csvg xmlns:='http...
This is the start of a data URI – or, to be more accurate, one of four different ways of writing such a data URI when working with SVG elements. Any one of these would replace the standard format when using background-image in a style sheet; the options available are:
<!-- base64 -->
background: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL...
<!-- UTF-8, not encoded -->
Background-url("data:image/svg+xml;charset=UTF-8,<svg ...> ... </svg>
<!-- UTF-8, optimized encoding for compatibility -->
Background-url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns:='http://...'
<!-- Fully URL encoded ASCII -->
Background-url("data:image/svg+xml;charset=US-ASCII ,%3Csvg%20...

The question is, which should we use? In short, the answer is the third one from the top; the reasons for this are a little complex (and involve getting into the depths of using gzip), but suffice to say that it provides the shortest string when converted into UTF-8 format. It is worth testing how many characters are required to create the data-URI strings in the remaining three options – data-URIs are known for producing lengthy strings, so we can choose which option gives us the shortest string, and therefore helps to keep code bloat to a minimum.

The developer Taylor Hunt has posted a useful article on Codepen, about optimizing SVGs in more detail – the article is available at https://codepen.io/tigt/post/optimizing-svgs-in-data-uris .

Leaving aside the choice of data-URI format to use, we should always work with optimized images where practical. Before we get stuck into our next exercise, let’s quickly cover off a nice easy way to perform that task, with the minimum of fuss.

Optimizing Our Image

Our next exercise relies on using an optimized image to make it as efficient as possible and not clutter up our style sheet with irrelevant code.

This is a subject we’ll cover in more detail, later in the book; for now, we’ll work on the basics, using an online service.

To optimize our image, go ahead and follow these steps:

OPTIMIZING THE SOURCE IMAGE

  1. 1.

    We’ll start by downloading the cart image – for this exercise, I’ve used the one available from linearicon.​com, at https://linearicons.com/free/icon/cart ; go ahead and click on Download SVG, then save the image to the img folder in our project area.

     
  2. 2.

    By default, the image will not be optimized, so it will contain extra XML code that should be removed before we convert it for use in our demo. For this, browse to https://jakearchibald.github.io/svgomg/ , then click on Open SVG from the hamburger menu.

     
  3. 3.

    Find the lnr-cart.svg icon from within our project area then click on Open to load the SVG.

     
  4. 4.

    At the bottom of the window, look for a blue circular button, which has an arrow pointing downward – click on this to download an optimized version of our image. Save this as cart.svg into the img folder of our project area. You can now close the browser window.

     

Now that we have an optimized image, let’s crack on with the main part of the demo:

CONVERTING SVG IMAGES TO DATA URIS

  1. 1.
    We’ll start with opening a new document and then adding the following code – save this as datauri.css in the css subfolder of our project area:
    @font-face { font-family: 'pt_sansregular'; src: url('../font/pt_sansregular.woff') format('woff'); font-weight: normal; font-style: normal;}
    body { font-family: 'pt_sansregular', sans-serif; padding: 2rem;
      font-size: 18px; }
    section > div { background-repeat: no-repeat; width: 20px; height: 20px; }
     
  2. 2.

    From the daturi folder that is in the code download that accompanies this book, go ahead and extract a copy of datauri.html – save this to the root of our project area.

     
  3. 3.

    We now need to prepare the URLs for each of our background images – we’ll begin with the standard base-64 version. Browse to http://b64.io/ , then drag and drop the cart.svg file into the green drop area – it will automatically display the base-64 encoded code in the window below.

     
  4. 4.

    Revert back to datauri.css, then leave a blank line. Take a copy of the code produced from step 2 and paste it into datauri.css – change the .cart class to section > div.base64 and save the file.

     
  5. 5.
    Next up comes the UTF-8 version – for this, go ahead and leave a line in our CSS file, then add this code:
    section > div.utf8 {
      background-image: url('data:image/svg+xml;charset=UTF-8,');
    }
     
  6. 6.

    Open a copy of cart.svg in a text editor, and take a copy of the code – paste it immediately before the closing single quote mark shown in the previous step.

     
  7. 7.

    We can optimize this a step further – leave a blank line in the CSS file, then copy and paste the previous section > div.utf8 style rule.

     
  8. 8.

    Rename this rule to section > div.utf8opt.

     
  9. 9.

    In the background-image attribute, look for these extracts of code:

    charset=UTF-8,%3Csvg xmlns and 291z"/%3E%3C/svg%3E');

    Go ahead and update as highlighted.

     
  10. 10.

    We have one more version left – that is to fully encode our SVG string, using a decoder such as the one by Eric Meyer at https://meyerweb.com/eric/tools/dencoder/ . For this, copy the code from charset=UTF-8, to (and including) the last character before the closing quote, from the div.utf-8 rule created in step 5.

     
  11. 11.

    Paste this into the encoder window in the above URL, then hit Encode.

     
  12. 12.

    In the background-image attribute, look for the charset=UTF-8, then delete everything upto (but not including) the closing single quote. Replace it with a copy of the code created in step 11.

     
  13. 13.
    Save the file – if all is well, we should see four instances of our cart, as displayed in Figure 3-3.
    ../images/461821_1_En_3_Chapter/461821_1_En_3_Fig3_HTML.jpg
    Figure 3-3

    The different Data-URL options available

     

Phew – that was a monster exercise! Some of you might ask how we can benefit from using this method: it is indeed a valid question! There are some benefits though to using this method (and some drawbacks too) – let’s pause for a moment to consider them in more detail.

Understanding How Our Code Works

The basic principle of using a data URI has been around since 1998, when it was first defined in RFC2397, in August of that year. Put simply, we convert an image (of some description) into a string of characters, which can be inserted into a background-image property within a style sheet rule.

Sounds simple enough, right? Well, there are some pitfalls we should consider: The more complex the image, the longer the string of characters – this might make our style sheet page simply too large and cumbersome to navigate.
  • Although we have four ways of creating data URIs, at least one of them isn’t recommended (base-64). The other three will produce differing results, so we need to choose the right method carefully.

  • We can’t make changes to the styling of a SVG image that has been inserted as a background image; we can only do this if we put our code inline.

Leaving these aside for the moment, let’s take a look at the code we created in more detail – we added in four different types of data URI as background images, which start with a data:image/svg+xml;base64 tag, for base-64 images, or this tag for native SVG images: data:image/svg+xml;charset=UTF-8.

Within each data URI tag is our string of characters – this will either be a base-64 encoded text (option 1), or the optimized XML from within our SVG image (options 2 to 4). The last three examples all use the same basic XML from within our SVG, but the data URI has been progressively encoded to ensure compatibility with web browsers.

Okay – let’s change tack: so far, our examples have focused on the basics of getting our image onto a page. In many cases, this will suffice, but what if we wanted to take it further? Traditionally we might do this using the likes of Photoshop – instead, how about using SVG to apply these effects? This opens up some real possibilities, such as using images to provide a color mask to SVGs – let’s dive in and take a look to see what this means in practice.

Applying Image Masks

If someone were to mention the words “mask” and “image,” then they could be forgiven for thinking that we’re trying to hide a problematic part of that image – that is absolutely not the case!

Granted, that was a terrible attempt at humor, but using masks opens up a whole host of possibilities. Our next exercise just scratches the surface of what is possible; how about using a mask with a SVG filter over an image, to really give it curve appeal? Or perhaps have a background image to which we apply a filter (turning it a shade of blue, for example), and then animate on various elements, to provide a welcoming effect on an agency home page?

These are two example of what is possible – we’re really only limited by the extent of our imagination. To get us started, and for our next exercise, we’re going to use a landscape image, over which we will apply an overlay effect – it’s a great effect if we want to provide some color to a background on a page, while still imparting relevant information to our visitor.

This demo is based on a Codepen example by Marco Barría with some slight tweaks – you can see the original at https://codepen.io/fixcl/pen/CHgrn

APPLYING MASKS

Let’s dive in and take a look at the steps involved:
  1. 1.

    We’ll start by extracting copies of the css and img folders from the masks folder in the code download that accompanies this book – save them to our project area.

     
  2. 2.

    Next, go ahead and take a copy of the datauri.html markup file, then delete the markup between the <head>...</head> tags, and the same within the <body> tags.

     
  3. 3.

    Add the following code between the <head> tags:

      <meta charset="utf-8">
      <title>Beginning SVG: Applying Masks to SVG</title>
      <link rel="stylesheet" href="css/masks.css">
     
  4. 4.

    Go ahead and add the following in between the <body> tags:

      <div class="overlay">
        <svg>
          <defs>
            <mask id="mask" x="0" y="0" width="100%" height="100%">
              <rect id="background" x="0" y="0" width="100%" height="100%"></rect>
              <text id="title" x="50%" y="100" dy="1.58rem">SVG Masks</text>
              <text id="subtitle" x="50%" y="0" dy="9.8rem">A quick demo</text>
            </mask>
          </defs>
         <rect id="base" x="0" y="0" width="100%" height="100%"/>
        </svg>
      </div>
      <section class="intro"></section>
     
  5. 5.
    Save the file as masks.html at the root of our project area – if we preview the results in a browser, we should see a landscape image, overlaid with a banner, as indicated in Figure 3-4.
    ../images/461821_1_En_3_Chapter/461821_1_En_3_Fig4_HTML.jpg
    Figure 3-4

    Applying an SVG mask to image

     

Interesting effect, huh? It’s a really simple one, but when used well it can make a page stand out. Most of the code within this demo focuses on styling the text and the background banner color; there is little in there that is unusual, with the exception of one rule. Let’s take a moment to explore how this demo works in more detail, and why one rule brings everything together.

Exploring How the Code Works

Our demo has only touched the surface of what is possible when applying masks – a really great effect that I’ve seen in use is to blur a strip of text across a background image (such as in a carousel), and to then add suitably sized text over the top. I could go on, but suffice to say it’s worth spending time on Google! But I digress…

Although we’ve used a fair number of rules in our style sheet, there are really only two parts that make the magic happen in our demo – the first is to apply a mask over our #base element:
svg #base { fill: black; -webkit-mask: url(#mask); mask: url(#mask); }
This particular property still hasn’t been fully ratified for use, hence the use of the –webkit vendor prefix; hopefully this will disappear over the course of time. We can’t have a mask without providing the content for that mask – this is taken care of within the <defs> block in our HTML markup:
  <svg>
    <defs>
      <mask id="mask" x="0" y="0" width="100%" height="100%" >
        <rect id="background" .../>
        <text id="title" ...">SVG Masks</text>
        <text id="subtitle" ...">A quick demo</text>
      </mask>
    </defs>
    <rect id="base" x="0" y="0" width="100%" height="100%"/>
  </svg>

So – what does a mask do? Put simply, it hides or “masks” an area specified using coordinates or an SVG shape; it has the effect of merging background and foreground images into one.

In this instance, the #mask reference in our CSS ties back to the mask defined in the <defs> block – we set a height of 100% square, starting at point zero. This contains a background element that we style with #666 (a very dark gray color); on top of this we add a main title and subtitle using <text> elements. Our mask is then applied to the <rect> element at the end of our SVG graphic, using the mask attribute provided in our style sheet.

Let’s move on – we’ve covered the use of images, and explored how we can create shapes…what’s missing? Ah yes: icons. There will be occasions where we might want to display some form of icon – credit card images, SSL security logos, and the like. We can of course display them individually – this will work, but as any good designer will say, it’s not ideal. To get around this, we can use that age old principle of creating sprites; what works for standard images will also work for SVG graphics, so let’s dive in and take a look.

Working with Icons

Icons have been around for decades – we use them to represent links to applications, buttons to click on, determine the state of a feature (aligning text, for example); the list is endless. They can be created in almost any format, although the universally accepted standard is the well-known .ICO format.

Irrespective of the format we use, there is a downside to using icons – the format does not lend itself to scaling well (if at all). The beauty of using SVG as a format though means this issue no longer exists – any icon we create in this format will scale perfectly, in the same way as their larger cousins.

There are dozens of different libraries available online that contain useful icons – two that come to mind are FlatIcon, available at https://www.flaticon.com/ ; and Simple Icons, from https://simpleicons.org/ . These make a perfect base for creating icon sprites; we can create these using the image route, or by creating a custom font. We’ll cover the latter method a little later in this chapter, but for now, let’s explore the image route in more detail.

Creating Image Sprites with Icons

Creating sprites is nothing new – we can do this using most common image formats, although for convenience it’s likely that most people will choose PNG or JPEG as their destination format. The same principles can be applied to SVG, although we have an extra route – for small projects, we can either manually create sprites by hand, or we can automate them using a technology such as Node.js. Let’s look at each option in turn.

If we decide to create them manually, then our SVG image will look something akin to this extract of code:
<svg style="display:none;">
 <symbol id="visa" viewBox="0 0 62 51">
   <path fill="#000000" d="M38.9872..."></path>
 </symbol>
 <symbol id="amex" viewBox="0 0 60 64">
   <path fill="#000000" d="M15.9264..."></path>
 </symbol>
...
</svg>

All we need is a text editor and our images – provided we can open each image and extract the relevant code, we can put together our SVG sprite. The only changes we need to make are to use <symbol> as the element for each sprite image, and that we need to provide both a selector ID and a suitably sized viewbox attribute in our code.

Using the <symbol> Element

We’ve touched on specifying our viewBox, but what’s this <symbol> element I see in our code…? Put simply, it’s a way of grouping elements together, for later reuse.

This last part is key – when working with SVG graphics, we can group elements together using the <g> element, and perform actions on all elements in a group simultaneously. The <symbol> element takes it further by allowing us to instantiate an instance later (as if it were a graphical template), with a <use> statement. This is perfect if we have a shape that can be displayed in a range of colors; we don’t need to implement separate SVG graphics for each, but instead reuse the base image multiple times.

To help with creating symbol elements, head over to https://svg-to-symbol.herokuapp.com/  – this will convert an existing SVG to use <symbol> elements.

Let’s move on – assuming our code has been added inline to the markup file, immediately after the opening <body> tag, we can then use the code thus, for the image to be displayed on screen:
<svg>
  <use href="#visa"></use>
<svg>

There are a couple of points we should be aware of though – notice how the SVG element has been styled with display: none? This is essential, otherwise we may find our images appear twice – once in the source file, and again as our sprite image. We can’t avoid this, so it’s something we have to get used to adding to our code!

The second drawback is size – creating a sprite manually really only suits small images, where the XML is manageable; this is really about being able to navigate through our code, than any speed issue! It’s for this reason that a more automated approach is beneficial – we can complete the process using an online service such as Iconizr, or take the task runner approach and use Node.js and a runner such as Gulp or Grunt. Let’s begin with a look at using an online service first.

CREATING AN SVG IMAGE SPRITE

There are a number of online services that allow us to create sprites, such as IcoMoon, or SpriteCow; my personal favorite is Iconizr, hosted at https://www.iconizr.com . Let’s work through the steps to create our sprite:
  1. 1.

    We’ll start by downloading our source images – browse to https://www.flaticon.com/packs/credit-cards-4 , then pick five images at random; I’ll assume for the purposes of this exercise that you’ve chosen banktransfer, paypal, visa, mastercard, and amex. Please adjust to suit if you decide to use different images.

     
  2. 2.

    Click on each icon in turn, then SVG | Download | Free download, to save the images to the img subfolder of project area.

     
  3. 3.

    We need to run through the optimization process for each – for this we’ll use the same optimization service at https://jakearchibald.github.io/svgomg/ , which we used earlier in this chapter.

     
  4. 4.

    Save optimized images to a new folder called svgo in our project area.

     
  5. 5.

    Next up comes the conversion process – for this, browse to iconizr.​com, then drag and drop all five into “Drop your SVG icons here” box.

     
  6. 6.

    Enter css/ into the CSS resource directory input field, then click on Create & download icon kit, to begin the conversion process.

     
  7. 7.

    It takes a little time for the process to run – when it is completed, click on Download icon kit

     
  8. 8.
    Extract the css folder within to our project area, then run the iconizr-svg-sprite-preview.html file in a browser to preview the results (Figure 3-5).
    ../images/461821_1_En_3_Chapter/461821_1_En_3_Fig5_HTML.jpg
    Figure 3-5

    Manually created SVG sprite

     
  9. 9.
    If we check the code markup in the file from the previous step – you will see something akin to the extract shown in Figure 3-6.
    ../images/461821_1_En_3_Chapter/461821_1_En_3_Fig6_HTML.jpg
    Figure 3-6

    Examining the sprite code in detail

    We can confirm that we’re using just one image, by checking out the Icons.svg file that will be in the css/icons folder, along with a PNG fallback version.

     

Tip

for a more in-depth look at creating SVG sprites, check out the article by Florens Verschelde at https://fvsch.com/code/svg-icons/how-to/ . It’s a little old but contains some useful tips!

We now have a useable sprite image, which can be referenced in code – this works perfectly well, but it is still something of a manual process that is dependent on demand on the Iconizr site. In this age of speed, we need something that removes this dependency – we can achieve this using Node and a task runner such as Gulp, so let’s dive in and take a look.

Automating the Process

The use of sprites should be at the forefront of any developer’s mind – it’s easy to see that with a little extra styling, we can dramatically reduce the number of images we need to use, which in turn reduces the resources we must from the server. Creating them though can be a thankless task – it’s one of those necessary evils, if we are to benefit from using sprites.

Trouble is, we’ve all got better things to do, right? I say better – in many cases, better is more likely to mean important, rather than interesting! This makes it all the more important for us to invest in automating this process if we can – it’s very likely we would use a Node.js-based task runner such as Gulp or Grunt. There are plenty of Grunt or Gulp-based packages that can help; it’s worth checking out the NPM Package Manager site at https://www.npmjs.com for ones you can try out.

As a start, you can take a look at https://github.com/jkphl/gulp-svg-sprite (for Gulp); or a Grunt equivalent, at http://www.grunticon.com/ .

For our next exercise, we will use Gulp to create our sprite, and the gulp-svg-sprite package – if you prefer to use a different task runner (such as Grunt), then this is fine; the process will be very similar. In any case, we will assume that Node.js has already been installed – if you didn’t install it earlier, then go ahead and do it now.

AUTOMATING THE CONVERSION

Assuming Node.js is installed and ready to go, let’s work through the steps involved:
  1. 1.

    We’ll start by installing Gulp – for this, fire up a Node.js command prompt, then enter this command and press Enter:

    npm install --global gulp-cli
     
  2. 2.
    When this has completed, go ahead and enter npm init at the prompt, then press Enter – this creates a package.json file, which is used by Gulp to store package dependencies. Enter the details as shown in Figure 3-7.
    ../images/461821_1_En_3_Chapter/461821_1_En_3_Fig7_HTML.jpg
    Figure 3-7

    Details for the package.json file

     
  3. 3.

    Next, we need to install Gulp itself – for this, enter npm install --save-dev gulp@next at the prompt, then press Enter.

     
  4. 4.

    We can now install the gulp-svg-sprite package – at the prompt, enter npm install gulp-svg-sprite --save, then press Enter.

     

If you get an issue with phantomjs not installing, then run this command at the prompt, and rerun step 5: npm install phantomjs –g

With the gulp-svg-sprite package now installed, we can prepare a quick demo to test that our sprite works:
  1. 5.

    In the Node.js command prompt window, enter gulp svg at the prompt, then press Enter. The sprite will be created – you will find it in the outputsymbolsvg folder, which is created automatically.

     
  2. 6.
    Go ahead and add the following code to a new file, saving it as autosprite.html within the outputsymbolsvg folder:
    <!DOCTYPE html>
    <head>
      <meta charset="utf-8">
      <title>Beginning SVG: Creating SVG Sprites</title>
      <style>svg { background-color: transparent; fill: slategrey; width: 140px; height: 140px; }</style>
    </head>
    </head>
    <body>
      <svg style="display:none;"></svg>
      <svg><use href="#american-express"></use></svg>
      <svg><use href="#bank-transfer"></use></svg>
    </body>
    </html>
     
  3. 7.

    We need to add in the XML from our SVG file – open sprite.symbol.svg, which is in the same folder, then replace the first <svg> tag with the contents of this file.

     
  4. 8.

    We need to make one small tweak to hide the core SVG file (our code will show the relevant sprite image later). For this, look for line 17, then edit it as indicated:

    <svg style="display:none;" xmlns:="http:...
     
  5. 9.
    Save the file – if all is well, we should see something akin to the screenshot shown in Figure 3-8.
    ../images/461821_1_En_3_Chapter/461821_1_En_3_Fig8_HTML.jpg
    Figure 3-8

    SVG images created from sprite

     

See how easy it was to convert to using sprites? Our demo uses just the one image; we instead make use of the <use> tag to insert the selected sprite image into our page. It is worth noting though that in case you’re wondering, the pure svg-sprite Node module does not read or write to the filesystem, so extra work is required to configure it; using a package for Grunt or Gulp will take care of this step automatically for us.

Use of Icon Fonts and SVG

At this point, I’m going to just touch on a different subject, but related to SVG icons: there are online services available that allow us to convert icons into a font file, for use in our pages. However, this is not without its issues; it is no longer a recommended practice. If you are interested in knowing more, then please check out the Working with Icon Fonts and SVG PDF I’ve created, and put in the code download that accompanies this book.

Okay – let’s move on: we’ve covered the use of images in SVG in some detail; how about we take a look at using text within an SVG graphic? There are some interesting options available to use, of which we’ll cover some of the more interesting ones later in this book. For now though, let’s look at the basics of using the <text> element within SVG.

Adding Text with the <text> Element

So far, all of our content has been largely visual – it goes without saying that “a picture paints a thousand words,” but there are occasions when we must use text to get across our message. Thankfully it is really easy to add text to an SVG element – take a look at this example:
<svg xmlns:="http://www.w3.org/2000/svg" width="600" height="160">
  <text x="50" y="100">SVG text styling</text>
</svg>

Look familiar? Although we’re working with a new element, we’ve already touched on using it; remember the embedded image of a moth orchid at the start of this chapter? The text displayed was added using such a <text> element.

The great thing about using a <text> element is that we can style it the same way as we would for normal text. Let’s put this into practice, and add a little color to the example markup as a new online pen using Codepen.

ADDING COLOR TO SVG TEXT

Let’s make a start:
  1. 1.

    Head over to https://www.codepen.io  – in the HTML window, copy and paste the markup from the start of this section.

     
  2. 2.

    Next, go ahead and add the following styles to the CSS window:

    @import 'https://fonts.googleapis.com/css?family=Oswald:700';
    text {  font-family: 'Oswald', sans-serif;  font-size: 72px;  stroke: rgb(117, 109, 106);
      stroke-width: 3px;  fill: rgb(240,213,184); }
     
  3. 3.
    Click on the Save button – if all is well, Codepen will automatically update, to display the text shown in Figure 3-9.
    ../images/461821_1_En_3_Chapter/461821_1_En_3_Fig9_HTML.jpg
    Figure 3-9

    Styling SVG text

     

Go ahead and try changing the colors or stroke-width – any changes you make will be automatically reflected in the pen.

I’ve created a version of this demo, which you can see at https://codepen.io/alexlibby/pen/mpQNWQ .

If we take a look at our code, we can see that most of it should be self-explanatory; attributes such as x and y are common to many SVG elements. However, this isn’t the extent of what is possible with the <text> tag; it’s a great opportunity to have a look at the key attributes for <text>, which are summarized in Table 3-1.
Table 3-1

SVG Attributes for <text>

Attribute / element

Purpose

x, y, dx, dy

The starting (x, y) and finishing (dx, dy) coordinates for a <text> element.

text-anchor

Used to align a string of text with reference to a given point (using the properties start, middle, or end).

rotate

One of several transforms that can be applied to an element and its children. Examples also include skew(), scale(), and translate().

Note: this is dependent on browser support for MathML – if this is not supported, then a CSS fallback will be used instead.

textLength

Specify the width of the space into which text will be drawn.

lengthAdjust

Controls how a specific string of text should be drawn into a <text> or <tspan> element, using spacingAndGlyphs or spacing to control the appearance.

<textPath>

Used to place text along any arbitrary path, using coordinates referenced from a defined <path> element.

<title>

Specifies a description string that is displayed when the description is text only. The <title> element is not rendered n graphics, but can sometimes be rendered as a tooltip, depending on the browser in use.

Our example worked very well, but I can’t help wonder if we can do more – after all, SVG is perfect for creating graphics that have been drawn, so why not do something bigger with text? Well, we can – let’s step it up a gear and create something a little more complex using the <text> element as part of our next exercise.

Applying Different Effects to Text

If someone posed the question, “What can one do with text when working with SVG graphics…?,” then the only answer must be “How long is a piece of string…?”

It might sound odd to answer a question with one, but the truth is – we are only limited by our imagination! If you search online, Google will return hundreds of results, where others have created all manner of examples of styled text. To really push the boat out though, and add some extra sparkle, animation may be required – SVG is a great format for animating elements; for inspiration, take a look at a post by Henry Wijaya at http://bashooka.com/coding/20-cool-svg-text-effects/ , or the collection on Codepen by Julia Buhvalova at https://codepen.io/collection/DPYwYN ?

We will cover animating SVG elements in more detail in Chapter 6, “Animating Content” – if we bring it back to reality though for now, we can still apply different patterns to our text within SVG. Our previous example touched on simply adding color and thicker edges to our text, but what about using images to style our text?

APPLYING SVG EFFECTS TO TEXT

This is an interesting effect – for it to work, it relies on using the right type of font, and in some respects the choice of image can also have an impact on our overall design. Let’s dive in and take a look:
  1. 1.

    In a new file, go ahead and take a copy of autosprite.html, then delete the markup between the <head> and <body> tags.

     
  2. 2.

    Next, add the following code in between the <head> tags:

    <meta charset="utf-8">
    <title>Beginning SVG: Adding Effects to Text</title>
    <link rel="stylesheet" href="css/texteffects.css">
     
  3. 3.

    We now need to add our SVG graphic – for this, paste the following code in between the <body> tags. There are a few steps involved, so I’ll break it down, starting with the opening <h1> and <svg> container tags:

    <h1>
      <svg viewBox="0 0 800 800" class="heading">
     
  4. 4.

    Go ahead and save this file as texteffects.html, at the root of our project area.

     
  5. 5.

    Next up comes the definitions block – we’re using this to define our pattern, which is a landscape image:

    <defs>
      <pattern id="img-pattern" patternUnits="userSpaceOnUse" width="800" height="800">
          <image href="img/landscape.png" x="0" y="0" width="900" height="900" />
        </pattern>
        </defs>
     
  6. 6.

    We then create our text element in a similar fashion as previously, before closing out our demo with the appropriate tags:

          <text text-anchor="middle" x="50%" y="20%" dy=".25rem" class="headingtext">
            Text Effects with SVG
          </text>
        </svg>
      </h1>
    </body>
    </html>
     
  7. 7.

    Our demo won’t be complete without some styling – for this, go ahead and add the following code to a new file, saving it within the css subfolder in our project area as texteffects.css:

    @import url('https://fonts.googleapis.com/css?family=Oswald');
    body { font-family: 'Anton', sans-serif; background: #3C3928; }
    .heading { font-size: 4.5rem; }
    .headingtext { stroke: rgba(255,255,255,.5); stroke-width: 0.1rem;
      fill: url(#img-pattern); letter-spacing: 0.1rem; }
     
  8. 8.
    Go ahead and save both the HTML markup and CSS files – if all is well, we should see this text, against a very dark grayish yellow background, as shown in Figure 3-10.
    ../images/461821_1_En_3_Chapter/461821_1_En_3_Fig10_HTML.jpg
    Figure 3-10

    Applying text effects

     
A beautifully simple demo, which can add some real sparkle if we apply it the right way – the irony though is that it only requires one line of code to bring it all together and make it work! Sure, our choice of font and image will play a part, but it all hangs on just one line:
fill: url(#img-pattern);

Let’s take a look at the code in more detail, to see how this simple but effective style works, and why we must choose the right font, color, and image for maximum impact.

Exploring How the Code Works

Our code begins with creating what should now be a familiar SVG container – we’ve applied a class of heading that we use to control the font size of our text (set at 4.5rem). We then set a definition block, into which we create our <pattern>, using the landscape image from earlier in the chapter. This pattern is set to 900px by 900px – this patternUnits value of userSpaceOnUse means it will adapt in size if it’s calling element (the <text> tag) changes in size.

We then create the all-important <text> tag – this is set to be centered in the middle of the screen, with the start point being set as 50% in, and 20% down. We’ve applied a class of headingtext, which is used to set the stroke, stroke-width and letter-spacing values – and of course our pattern! We then tie off our design by setting the background color to #3C3928, or a very dark grayish yellow color.

Embedding Other Content

Adding images and SVG graphics a page is a start, but we can take things even further – how about adding video? It has to be said that with the current state of HTML5 video, this might not immediately make sense; most recent browsers will play MP4 format natively, without the need to embed it within a container.

However – embedding it as part of a SVG does open up some interesting opportunities for us: any <text> elements within can be crawled for SEO purposes; we can add subtitles for different languages without having to edit the original video, and can also overlay elements with ease. Above all, though, we can make our video responsive – provided we don’t set static size values for the video within, then it will automatically resize if our SVG container element changes size.

How does it work? To embed our video, we make use of the <foreignobject> element – this can contain almost any element that is not native SVG, such as HTML video, or longer texts, where the HTML format is easier to manipulate and manage than the SVG equivalent. Adding in our content is very straightforward, so let’s dive into our next exercise to find out how it all works in practice.

Adding Videos

For our next exercise, I’m going to revisit a favorite haunt of mine – anyone remember the Big Buck Bunny Project?

No – don’t worry: this is not a reference to some wild animal-based website! It’s one of several movies created by the Blender Foundation, created using the open source Blender tool. We’re going to use another of their videos for our next exercise – “Sintel”, which was premiered in September 2010. The original movie is still available from https://durian.blender.org/ ; we’ll make use of the MP4 version in our next demo.

ADDING VIDEO TO SVG ELEMENTS

Let’s make a start:
  1. 1.

    We need to download some assets first – go ahead and extract copies of the css and video folders from the foreignobject folder in the code download that accompanies this book, and save them to our project area.

     

There is a font folder also in the code download – it contains the same font file from previous demos, so you only need to download it if you don’t already have it in your project folder.

  1. 2.

    Next, take a copy of the texteffects.html file, and delete the content from within the <head> tags, then the content from within the <body> tags. Save this as foreignobject.html at the root of our project area.

     
  2. 3.
    Add the following code in between the <head>...</head> tags:
      <meta charset="utf-8">
      <title>Beginning SVG: Creating SVG Sprites</title>
      <link rel="stylesheet" href="css/foreignObject.css">
     
  3. 4.
    Next, add the following SVG markup in between the <body> tags:
      <svg xmlns:="http://www.w3.org/2000/svg">
        <g>
          <rect x="0" y="0" width="300" height="200"></rect>
          <foreignObject x="-151" y="-104" width="500" height="400">
            <video controls="">
              <source src="video/sintel.mp4" type="video/mp4">
            </video>
            <p>Trailer for "Sintel"</p>
          </foreignObject>
        </g>
      </svg>
     
  4. 5.
    Go ahead and save the file – if all is well, we should see (and be able to play) our video, as shown in Figure 3-11.
    ../images/461821_1_En_3_Chapter/461821_1_En_3_Fig11_HTML.jpg
    Figure 3-11

    “Sintel” video embedded as SVG

     

Although our code may look complicated, in reality it isn’t – we start with defining a standard SVG graphic. Inside this, we create a <rect> of 300px by 200px, followed by our <foreignObject> element.

It’s inside this we set up our video tags – for the purposes of our demo, we’re referencing a single MP4 video, but we could easily add in links for other formats such as OGG or WebM if needed. We then include a standard <p> tag for our text, before closing the SVG element – when using a <foreignObject> tag, the one thing we can’t include inside it is SVG elements!

Okay – let’s move on: many of the examples we’ve used have been somewhat theoretical; we’re going to round out this chapter with one more example of a practical example, making use of an online tool that…well, if I had a dime for every time I used it, I might have retired somewhere warm and sunny, and lived off the proceeds….

Implementing a Real-World Example

Cast your mind back to the Adding Markers to SVG Paths” demo we created back in Chapter 2, “Creating Shapes” – remember how we touched on creating markers, the basis of which we might use to create suitable indicators for Google Maps?

Well, it’s time for a little trip down memory lane – our next exercise, in case you hadn’t already guessed – is going to be about one of my favorite tools: Google Maps! Yes, it may have only been around since 2005, but it has become one of the most popular tools on the web; it allows use of SVG, so it seems fitting to explore this in more detail.

ADDING MARKERS TO GOOGLE MAPS

Now, before we get started, there is an important point to be aware of – Google Maps will only accept SVGs if they contain a single path. That makes anything more complex than a simple image impossible, so how can we get around this?

Fortunately there is an option: the developer John Hoover has created the SVG Marker overlay object (available from https://github.com/defvayne23/SVGMarker ) that allows us to use more complex SVGs with Google Maps. It’s really easy to use, so without further ado, let’s make a start:
  1. 1.

    We’ll begin by downloading copies of the css and img folders for this demo, from the svgmarkers folder in the code download that accompanies this book – go ahead and store these in our project area.

     
  2. 2.

    Next, add the following code to a new file, saving it as svgmarkers.html at the root of our project folder:

    <!DOCTYPE html>
    <head>
      <meta charset="utf-8">
      <title>Beginning SVG: Adding SVG Markers to Google Maps</title>
      <link rel="stylesheet" href="css/svgmarkers.css">
      <script src="https://maps.google.com/maps/api/js"></script>
      <script src="js/SVGMarker.min.js"></script>
      <script src="js/markers.js"></script>
    </head>
    <body>
      <h2>Location of Apress Media:</h2>
      <div id="map"></div>
    </body>
    </html>
     
  3. 3.

    With our markup in place, we now need to make our map work – for this, go ahead and download the SVGMarker library from https://raw.githubusercontent.com/defvayne23/SVGMarker/master/SVGMarker.min.js , and store this in a new js subfolder within our project area.

     
  4. 4.

    The SVGMarker library allows us to convert an SVG image into something that Google can use – we now need to tie it into our map. For this, go ahead and add the following code to a new file, saving it as markers.js in the js subfolder from the previous step:

    window.addEventListener('load', function() {
      var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 19,
        center: new google.maps.LatLng(40.7255945,-74.0051243)
      });
      var marker = new SVGMarker({
        map: map,
        position: new google.maps.LatLng(40.7255945,-74.0051243),
        icon: {
          anchor: new google.maps.Point(90, 90.26),
          size: new google.maps.Size(120,90.26),
          url: 'img/apresspin.svg'
        }
      })
    });
     
  5. 5.
    Save all of your files, then try previewing the results in a browser – if all is well, we should see the location map for Apress Media in New York, as indicated in Figure 3-12.
    ../images/461821_1_En_3_Chapter/461821_1_En_3_Fig12_HTML.jpg
    Figure 3-12

    Location of Apress Media in New York

     

This opens up some great possibilities – we could of course create our marker(s) using a format such as PNG, but at the risk of losing sharpness if the image were to be resized. SVG is perfect for this format, although there are a couple of considerations – let’s dive in and explore the practicalities of using this format with Google Maps in more detail.

Understanding How It Works

At face value, if we were to compare the code used to create our map with that provided by Google, we wouldn’t notice any real change. Sure, the configuration options may be in a different order, but it will still have the same effect.

So how does it work? The magic lies in the SVGMarker.min.js file – it’s too large to reproduce here in full, but in a nutshell, it takes a copy of the icon we’ve specified, and draws it as an image that is superimposed onto the map. The beauty of this solution is that we can configure our map object in exactly the same way as for a standard PNG or JPEG image , as the work to translate it into a format Google Maps can understand, is handled by the SVGMarker object.

It does raise an important question though: surely we could convert all of our SVG graphics into data URIs, and insert this into our code. Wouldn’t this be better – allowing us to resize or manipulate it? Well – the answer is both yes and no: it will depend on the size of the code required to create our SVG.

If the code we’ve used to create this graphic is large, then adding this (and other images) to our markup will clearly make it larger and less manageable. There will come a point where it is too large to manage, and that this will have an effect on page load times. This is something we clearly want to keep to a minimum, so we just need to be mindful of how many images we turn into data-URIs, so that we keep a sensible balance between calling external images, against those listed inline within our code.

Summary

Phew – we’ve certainly covered a lot over the course of this chapter! Although SVG graphics are ideally suited for creating 2D images, it doesn’t stop us from using the format to host other media, such as images and videos. We can create some great effects when working with images and SVG – let’s take a moment to review what we’ve covered over the course of this chapter.

We kicked off with a quick look at embedding an image within a SVG graphic, before starting with a look at exporting images, so that we have both SVG and PNG versions available as source images. We then moved onto covering the different formats of data URIs, and saw how the level of optimization can have a beneficial effect on the resulting code. We then moved onto understanding how we can use image masks to add a simple but effective overlay to an image, and saw how we can use it to provide a title or header effect to a background image.

Next up came a look at working with icons – we explored how easy it is to create image sprites, before making use of the icons from within SVG graphics. We covered both the manual route and how to set up an automated process; we covered how the former route may suit occasional use, and that for anything more than the odd icon, the automated route may be a better option.

We then moved onto learning how to apply effects to text elements within a SVG graphic – we covered a couple of simple examples, as a taster for what is possible, and that this is only limited by our imagination.

We then rounded out the chapter with a look at incorporating videos – we saw that in this day and age of social media, there is still a use for SVG and video, even though the latest HTML5 video standards are more than capable of displaying content. Last, but by no means least, we finished with a real-world demo, where we added an SVG marker to a Google Map – we saw that although this is really easy, current limitations prevent anything more than a simple marker, and that with some trickery, we can work around that limitation!

Right – onwards we go: there is never any rest for the wicked! One of my favorite topics in web development is making content responsive; with more and more people viewing the web on mobile devices, it is so important to have a site that works well for this platform. SVG has a number of features that makes it suited to Responsive Web Design (and by default, sizing content easily), so go ahead and turn that page to find out more…

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.172.115