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

4. Sizing SVG

Alex Libby1 
(1)
Rugby, Warwickshire, UK
 

In Chapter 3, we worked our way through creating different types of SVG elements – this includes the humble square, through to a circle and finishing up with more complex paths. Yet one key feature remains, upon which we’ve touched, yet not really discussed in any detail – scaling. If we have to scale up a standard image, then this becomes tricky; in most cases we end up with a picture that…well, looks rubbish!

SVG graphics are different: we can take any SVG element and resize them with ease and without loss of clarity. How? Well, it all hangs around the SVG coordinate system and the SVG viewport; it’s key to how SVG graphics work. A good analogy would be a well-known online map application – no prizes for guessing which one! With that in mind, let’s kick off with a look at the basic principles in more detail.

Understanding Scalability

A question – what might Google Maps and your browser have in common with SVG, I wonder? No, I’ve not completely lost the plot; this is a very good analogy for how SVG elements work. Let me explain more:

If you ever look at a Google Map, you’re only looking a small part of what is an infinite-sized canvas – clearly our browser could never be wide enough to view everything! In this instance, our browser acts as a viewport (or window) to the canvas; the content on that canvas is our SVG graphic. We can use controls provided by Google to pan around the map, or zoom in; no matter how much we move, we will only ever see a small part of that canvas.

Still with me so far? Good – let’s hold that thought for a moment and turn our attention to a small demo: in it we will see some of the effects that moving the canvas around will have on our SVG elements.

SCALING SVG GRAPHICS

Okay - let’s make a start:
  1. 1.

    In a new document, go ahead and add the following code, saving it as scaling.html at the root of our project area:

    <!DOCTYPE html>
    <head>
      <meta charset="utf-8">
      <title>Beginning SVG: Scaling an SVG Graphic</title>
      <link rel="stylesheet" href="css/scaling.css">
    </head>
    <body>
      <svg width="500" height="100">
        <circle r="25" cx="25" cy="25" fill="dimgrey" />
        <rect x="500" y="100" width="50" height="50" fill="#933" />
      </svg>
    </body>
    </html>
     
  2. 2.

    Next up, we need to add a couple of styles to our demo – although the core part of the demo has most of them, there are a couple we need to finish it off. Add the following rules to a new document, saving it as scaling.css within 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; }
    svg { outline: 5px solid #000; }
     
  3. 3.

    Go ahead and save the files – if we preview the results, we’ll a circle within a box, as indicated in Figure 4-1.

     
../images/461821_1_En_4_Chapter/461821_1_En_4_Fig1_HTML.jpg
Figure 4-1

Our initial SVG, before scaling

At this point, we’re going to alter how the circle looks, by changing our code – we’ll start by adding a viewBox parameter to our code:
  1. 4.

    Go ahead and add the following code in, immediately after the <height> parameter for our SVG element:

    height="100" viewBox="0 0 500 100"
     
  2. 5.

    What happens if we alter the viewBox attribute to this: viewBox="25 25 500 100"?

     
  3. 6.

    Let’s focus on one of the shapes – go ahead and remove the <rect> line from within our SVG, then set the viewBox values to "0 0 250 50". Notice how the circle has increased in size?

     
  4. 7.

    As a final change, go ahead and update the opening SVG tag as indicated:

    <svg width="500" height="100" viewBox="0 0 50 100" preserveAspectRatio="none">
    We will see the circle expand to fit the SVG container, as indicated in Figure 4-2.
    ../images/461821_1_En_4_Chapter/461821_1_En_4_Fig2_HTML.jpg
    Figure 4-2

    Scaled SVG of a circle

     

Over the course of this exercise, we’ve not made any changes to our circle element, yet you will have noticed that after each change, it has altered shape. What gives? Unlike ordinary images, SVG images don’t resize in quite the same way – let’s take a breather to explore this in more detail.

Understanding the Impact of Scaling

At this point I’m sure you will be asking just how we managed to make our SVG graphic change shape and position, without changing its sizes. The key to it lies in the viewport – we’re not moving our SVG, but moving the viewport instead:

We initially don’t see any change once we’ve run step 3 and added in the viewBox attribute – our viewBox is 500px by 100px, which is identical to the viewport. Notice though that we’ve specified both a circle and a square in our SVG, yet only the former is showing? If we change our viewBox values to 25 25 500 100, this shifts our canvas up and to the left; this aligns it to the origin (25, 25), hiding part of the circle and revealing the top part of the square.

When we remove the square element and change the viewBox values, we don’t shift the canvas this time, but set the viewBox to only cover half the width and height of our viewport. This has the effect of scaling our viewBox, so that all four corners align with the viewport – this doubles the size of the canvas, scaling the circle to twice the size to fit.

If we had doubled the size of our viewBox values, then this would have had the opposite effect of shrinking our graphic – there is twice as much to cover in the same space, so the elements are shrunken to fit.

Our final change completely alters the aspect ratio of our circle – the viewBox is set as 1:2, against the viewport, which has a ratio of 5:1. This means that the circle’s height is stretched by a factor of 10, but its height remains constant; the stretching comes from the presence of preserveAspectRatio to none.

Okay – let’s move on: over the course of this exercise, we’ve touched on some of the key concepts for scaling SVG graphics. At the heart of this scaling lies the SVG coordinate system, which controls where our canvas is displayed. Each time we create a new SVG element, we also create a new coordinate system; let’s take a look at how it works in more detail.

Getting to Grips with SVG Coordinates

If you recall from the start of this chapter, we talked about our SVG canvas as being of infinite size – our viewport on this canvas being akin to a window through a wall that covers the entire size of our canvas.

Each time we create a new SVG element, we also create a new coordinate system, with an infinite canvas where point zero (0,0) is at the top left of our parent element (such as a div). Specifying positive values on either axis will move an element down or to the right. Negative values will move it in the opposite direction, or upwards and to the left of our canvas.

We can see this in more detail, in Figure 4-3.
../images/461821_1_En_4_Chapter/461821_1_En_4_Fig3_HTML.jpg
Figure 4-3

Schematic of the coordinate system

By default, the coordinate systems of each canvas and viewport will align with each other, although (as we saw in the previous exercise), this does not have to be the case; we can change the alignment to suit our needs. This includes the unit of measure we use to position elements; we can use any unit, with the exception of percentage values, and then we can mix and match which units are used in each system, within our projects.

Applying Coordinates to an SVG

Enough of the talk – let’s get stuck into some code! As any teacher will say, there is no substitute for practice, so over the course of the next couple of pages, we will work our way through some examples of creating and positioning SVG elements, so we can see the effects of setting values as coordinates for an SVG drawing.

For this exercise, we’re going to make use of Codepen as an interactive demo – this means we will see the results of our change immediately, without having to manually refresh the screen:

MOVING SVG ELEMENTS

Let’s make a start:
  1. 1.

    We’ll start by creating a simple demo in a Codepen  – head over to https://codepen.io , then add this code into the HTML section:

    <svg width="600" height="300">
      <rect x="0" y="0" width="200" height="100" />
    </svg>
     
  2. 2.

    We need to add some simple styling – for this, drop the following code into the CSS section of our Codepen:

    svg {
      outline: 5px solid #000;
      overflow: hidden;
    }
    rect {
      fill: slategray;
    }
     

At this point, we’ve created a viewport of 600px by 300px, with a silver gray rectangle inside, measuring 200px by 100px. At present, as no units of measure have been specified, it assumes a default of pixels; we could easily have specified a different unit as desired.

Our SVG demo also has an outline, so we can see where our rectangle is – everything inside the outline forms our viewport. The lone rectangle is in the top left corner, which aligns with the viewport; if values are not specified for the starting point, then it assumes a default of 0,0, or zero point.

It’s worth noting that if we had not specified values for the size of our <rect>, then most browsers will use a default of 300px x 150px. It’s not consistent, so it is better set values if you can!

Let’s return back to our exercise –
  1. 3.

    Try changing the starting points for our rectangle, as indicated:

    <rect x="10" y="10" width="200" height="100" />

    Notice how it moves away, down and to the right, by 10px? Changing the x and/or y coordinates in this manner will move the element on our canvas – it’s important to note that our neither our canvas nor our viewport have moved; only the rectangle has been displaced.

     
  2. 4.

    This time, try changing the values as shown in this example:

    <rect x="-100" y="-50" width="200" height="100" fill="#f00" />
     

This time, only part of our rectangle is visible – the rest has been drawn, but falls outside of our viewport. In this instance, we’ve only moved it by a few pixels, but there is nothing stopping us from drawing our SVG anywhere on our canvas (which could be measured in billions of pixels – yes, billions of pixels!).

  1. 5.

    What happens if we needed to see outside of our viewport? This is normally set to be hidden by default, but no problem – go ahead and make this change to our CSS, to reveal our (hidden) SVG:

    svg { outline: 5px solid #000; overflow: visible;  margin: 50px 0px 0px 150px; }
    We can see the results of our change (including the displacement), in this extract, shown in Figure 4-4.
    ../images/461821_1_En_4_Chapter/461821_1_En_4_Fig4_HTML.jpg
    Figure 4-4

    Our (exposed) overlapping SVG

     

The changes we’ve made in our exercise have been very straightforward, yet we’ve only scratched the surface of what is possible! Trouble is, we’re still a little limited in what we can do: How can we take things further? Well, the answer comes in the form of a useful little toolkit – it may be small, but it will help earn its keep when working with SVG: let me introduce the SVG Scaling Toolbox.

We’ve already used parts of it in previous exercises, but as scaling SVGs can be tricky, it’s worth spending some time to get to know it in more detail. It comes in several parts – we’ll kick off with a look first at setting heights and widths of SVG elements.

Introducing the SVG Scaling Toolbox

At this point, I can already hear the next question coming – what is this Toolbox all about…? Well, to answer this very pertinent question, I need to step back for a moment:

If we resize any image, we have an idea about how they should scale, correct? After all, raster format images such as JPEGs or PNGs have a clearly defined size, and that we can include an option to automatically scale a particular dimension if we only provide height or width, but not both.

SVGs don’t operate in the same way – they are not images but documents that require a different mindset when scaling. It means that not only do we need to control the size of our canvas, but also the elements within. It means that scaling considerations increase: we need to be mindful of the size of the canvas, whether the image should maintain a height to width ratio, should the image scale uniformly, or can we allow for some distortion?

This is where the Scaling Toolbox comes into play – its assorted attributes will help retain some sense of order when it comes to scaling images. The first tool to understand is the height and width attributes – but there is a sting in this tale…

Setting Height and Width Attributes

When adding SVGs to a page (assuming we use one of the methods we touched on back in Chapter 1), we can set both height and width sizes directly in code, using something akin to this:
<svg width="500" height="300"></svg>

This seems pretty reasonable, right? We can use any one of several different units of measure, such as ems, rems, picas, or even millimeters (mm) – SVG can use standard CSS units when referring to dimensions of an image.

In our example, the <svg> element doesn’t specify any units though; by default, this equates to pixels, unless we specify a named unit. Now – assuming we have set suitable values: at first glance, one would expect any set on an SVG container, to implicitly set an aspect ratio, so that an SVG will scale in the same way as normal images. Sound reasonable, right…?

Unfortunately, this is not the case – setting height and width on an SVG can end up being counterproductive:
  • If your SVG is embedded using <img> tags, then setting values will make the element scale as predicted in most browsers, save for Internet Explorer. It’s likely that you will see the SVG element automatically scaled to maintain a constant aspect ratio in IE, but that the content within will not be scaled.

  • Although their use has fallen out of favor, setting heights and widths on an <object>, <embed> or <iframe> will not change the frame size; you will end up with scrollbars if the SVG is too large.

  • If you have set your SVG inline, this will control both the image area on the page, and the content within. So, any CSS we set on the <svg> element, such as svg {width: 100%; height: auto;}, will override anything set within the SVG code. In this case, setting these dimensions will set a default height of 150px or 100vh, depending on the browser we use.

There’s one word that comes to mind – ouch! The safest way to control width and height is to not set it in code. Instead, set it within your CSS; this will allow the SVG to scale accordingly. To be sure that we set a suitable aspect ratio, and that the drawing scales to fit, we need the second tool in our kit – the viewBox. We’ve already used it a few times, so let’s take a moment to explore this in more detail.

Implementing a viewBox

Until now, we’re using a canvas that could be of any size, and that we’ve applied something called a viewBox to define the extent of what we can see at any one point. But – what really is a viewBox, and how does it work when we apply it to our code?

Well, the viewBox is what makes the S of SVG – it makes our vector graphics scalable. Consider this example, where the viewBox attribute has been highlighted:
<svg width="400" height="300" viewBox="0 0 40 30">
  <rect x="20" y="10" width="10" height="5" style="stroke: #000000; fill:none;"/>
</svg>

This little example creates an <svg> element with a width of 400 pixels and a height of 300. We’ve applied a viewBox attribute to the <svg>, which contains four coordinates, to define the view box of the <svg> element. These coordinates start with the x and y starting points (“point zero”), with width and height controlling its size.

It’s worth noting that if we were to work with other non-SVG elements, then the CSS properties object-fit and object-position work in a similar manner to the viewBox attribute.

If we set a viewBox attribute (as in our example), we can use this to control the following:
  • The aspect ratio of our image.

  • How all the lengths and coordinates used inside the SVG should be scaled to fit the total space available.

  • The origin (or point zero) of the SVG coordinate system, where x and y equal 0.

We’ve already seen in several code examples that the viewBox settings are a list of four numbers, separated using commas or spaces, which control the starting position and size of our viewBox. These values will default to pixels, unless we specify a different unit of measure.
  • The first pair of values set the starting point (or point zero) of our viewBox, in a similar fashion to setting it in JavaScript. For simple scaling, we can set both to zero; centering the coordinates will make it easier to define and transform shapes (as opposed to performing these actions from a corner), or to crop an image to a smaller size than its original definition.

  • The second pair of values represent the width and height of the content that should be scaled to fit the area into which we’re drawing our SVG. It’s worth noting that if our SVG uses a different unit of measure (such as centimeters), then it will be scaled to match the overall scale set by the viewBox.

Okay – with that in mind, let’s take a look at a couple of example viewBox values, to see how this works in practice:
  • Imagine we had set a viewBox="0 0 100 100": this defines a coordinate system which is 100 units wide and 100 units high. If we had placed a circle in the center of our graphic, with a radius of 50px, then this will fill the whole screen, even if we tried to resize our browser window! If we’d set a <rect> element instead, with a height of 1in, this would almost fill the screen – 1 inch equates to 96px in CSS, and each side would be scaled to the same length.

  • If however we had set a viewBox="5 0 90 100", then we would have had almost the same view. This time though, it would be cropped in by 5px on the left and right, so that the total width equates to 90 pixels.

When we’ve set a viewBox in our code, our SVG graphic will scale to fit its size, without loss of quality. However, we should note that it will not by default stretch or distort the image if the dimensions we’ve given it do not match the aspect ratio that has been set. Instead, the scale will change to preserve the aspect ratio that has been set – this is set using the preserveAspectRatio attribute, so let’s dive in and see what this in means for us in more detail.

Preserving the Aspect Ratio

Ask anyone to think of famous double acts, and one might get a variety of answers – Cagney and Lacey, Smokey and the Bandit…the list is endless! How does this relate to SVGs, I hear you ask…?

Well, leaving aside the reference to well-known films, one might say that the viewBox parameter is but one half of a double act (if you excuse the pun!) – It’s partner in crime is preserveAspectRatio. By itself, it has no effect on our SVG, but when teamed up with viewBox, its role is to define how an image should be scaled, if the viewBox doesn’t match our viewport’s aspect ratio.

In most cases, we can simply set it with default behavior, which works well in most cases – our image will be scaled until it fits the available space, allowing for any extra space around the image.

If, however, we need to tweak its behavior, preserveAspectRatio comes with two parameters that we can adjust:<align> and <meetOrSlice>. Let’s take a look at these properties in more detail, beginning with the compulsory <align> attribute; the details of which are listed in Table 4-1.
Table 4-1

Attributes for Aligning the viewBox

Value

Description

xMin

Align minimum x of view box with the left edge of the viewport.

xMid

Align midpoint on the x-axis of view box with the center of the viewport on the x-axis.

xMax

Align maximum x of view box with the right edge of the viewport.

YMin

Align minimum y of view box with the top edge of the viewport.

YMid

Align midpoint on the y-axis of view box with the center point of the viewport on the y-axis.

YMax

Align maximum y of view box with the bottom edge of the viewport.

For a full list of options, please refer to https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio .

Although the properties are listed individually in Table 4-1, they are designed to be combined into one value, such as in these examples: xMaxYMax and xMidYMid. They look very similar (and yes, the change in case is deliberate), but their behavior on our SVG will be different. The first example aligns the right edge of the viewBox with the right edge of the viewport, whereas the second aligns the middle of the viewBox with the middle of the viewport. These are not the only comnbinations we can use – the full list is shown in Table 4-2.
Table 4-2

Possible Combinations of Alignment Keywords

 

Left

Center

Right

Top

xMinYMin

xMidYMin

xMaxYMin

Center

xMinYMid

xMidYMid

xMaxYMid

Bottom

xMinYMax

xMidYMax

xMaxYMax

The second parameter, <meetOrSlice>, is optional; it can be included if needed, but should separated by a space as indicated in this example:
preserveAspectRatio="xMidYMid meet"
For this parameter, we can specify any one of the following three values – meet, slice or none; the role each plays is detailed in Table 4-3.
Table 4-3

Values for preserveAspectRatio

Value

Description

meet

Preserves aspect ratio and scales view box to fit within viewport.

slice

Preserves aspect ratio and slices off any part of the image that does not fit inside the viewport.

none

Does not preserve aspect ratio. Scales image to fit view box fully into viewport. Proportions will be distorted.

An interesting point worth noting that this second attribute works in a similar fashion to standard CSS for background images – the closest equivalent for meet is background-size: contain, and for slice, we could use background-size: cover. The only thing to be aware of is that when using slice, it will scale the image to the largest dimension, and may or may not slice off the rest – the latter depends on how we have (or have not) set the value of the overflow property!

We may of course decide not to specify a value at all, and rely on it simply using the default of none. This allows the SVG to scale more like a raster image (but clearly with better resolution) – it will stretch or squash the image to fit the height and width values specified in our code.

To really understand how the coordinate system works, and the impact of changing viewBox or preserveAspectRatio properties, I would recommend trying out the interactive demo by Sarah Soueidan, at https://www.sarasoueidan.com/demos/interactive-svg-coordinate-system/  – this is a great eye-opener!

Right – enough chitchat: time we got physical with some code! Although the Scaling Toolbox attributes may look straightforward enough, their simplicity belies the strength of their power; let’s put some of that to use, with a quick demo to see the impact of setting these values in code.

Putting the Toolbox to Use

Over the course of the last few pages, we’ve talked in detail about the Scaling Toolbox – although the settings within are not complex, it’s all about the interaction and finding the right balance for our needs.

There’s no better way to get accustomed to achieving that balance, than in a demo – for our next exercise, we’ll use a simple graphic of an apple, to explore how setting the various properties of the toolbox can have an impact on the appearance of our image.

PRESERVING SIZE

Before we start our exercise, there is a simple task we need to perform – we need an SVG; for this, I will use one of an apple that I’ve sourced from https://openclipart.org/detail/183893/simple-red-apple . You can of course use any for this, although I would recommend keeping it as simple as possible!

Okay – assuming we have our graphic, let’s make a start:
  1. 1.

    We’ll begin with setting up our markup – in a new file, go ahead and add the following code, saving it as preserve.html at the root of our project folder:

    <!DOCTYPE html>
    <head>
      <meta charset="utf-8">
      <title>Beginning SVG: Setting preserveAspectRatio</title>
      <link rel="stylesheet" href="css/preserve.css">
    </head>
    <body>
      <h2>Beginninng SVG: Preserving Aspect Ratio</h2>
      <div class="center"> </div>
    </body>
    </html>
     
  2. 2.

    We need to add a couple of styles – for this, download a copy of the preserve.css file, and drop it into the css subfolder that’s in our project area.

     
  3. 3.

    Next, we need to add our SVG – for this, I will use a graphic of an apple (which is available in the code download). Go ahead and extract a copy and save it to the img folder, which is in our project folder.

     
  4. 4.

    As good practice, we should ensure it is optimized – we can do this quickly using the SVGO online service, available at https://jakearchibald.github.io/svgomg/ . Browse to the site, then drag and drop the image file straight over the top; once optimized, you can save a copy of the results by clicking on the white arrow and saving the file to our img folder.

     

I would suggest saving it as a different name – we don’t link to the file directly from our demo, but copy the contents into our markup. Saving a copy means you can then compare images, to see how optimization can remove redundant code.

  1. 5.

    We now need to add the content of our SVG – go ahead and open the SVG in your text editor, then copy and paste the contents in between the <div class="center"></div> tags.

     
  2. 6.

    Next, add in this attribute to the SVG code, as indicated:

    viewBox="0 0 442.23 482.04" preserveAspectRatio="none">

     
  3. 7.
    Save the file – if we preview the results, we will see something akin to the screenshot shown in Figure 4-5.
    ../images/461821_1_En_4_Chapter/461821_1_En_4_Fig5_HTML.jpg
    Figure 4-5

    Effect of not setting preserveAspectRatio

     
  4. 8.
    Try changing the preserveAspectRatio value to meet, as indicated: preserveAspectRatio="xMidYMax meet", then refresh the screen – you should see a smaller apple, as shown in Figure 4-6.
    ../images/461821_1_En_4_Chapter/461821_1_En_4_Fig6_HTML.jpg
    Figure 4-6

    Shrinking our apple

    This time, let’s take a different tack: keep the slice attribute, but alter the viewBox values as highlighted: viewBox="0 0 430 250" preserveAspectRatio="xMidYMax slice" – what do you get? You should see our apple zoomed in, as shown in Figure 4-7.
    ../images/461821_1_En_4_Chapter/461821_1_En_4_Fig7_HTML.jpg
    Figure 4-7

    Zooming in on our apple

     

Phew – see what a difference changing just one word or digit can make, to our SVG? It’s all about where we want to position our graphic, and whether we need it to all display as much as possible within the viewport, or are happy for parts to be sliced off (hidden) as needed. This is an important concept to master, so let’s pause for a moment to explore how our demo works in more detail.

Understanding How It Works

So – what did happen in our demo? The key to understanding it is that we have not changed the image itself (even though it may appear so), but we have changed how we view that image. Let me explain what I mean:

If we list all three viewBox examples, then we have the following code:
  • viewBox= "0 0 442.23 482.04" preserveAspectRatio="none"

  • viewBox= "0 0 442.23 482.04" preserveAspectRatio="xMidYMax meet"

  • viewBox= "0 0 430 250" preserveAspectRatio="xMidYMax slice"

Notice how in two out of the three cases, our viewBox doesn’t change size; in the third example, we reduce the size, which has the effect of zooming in on our image, so it becomes more enlarged.

Our first example sets preserveAspectRatio to none – this tells our viewBox to scale to fit the size of our viewport, effectively (in this instance) aligning both to the same set of coordinates as each other. The net effect of this is that the image itself is not scaled accordingly but squashed into whatever dimensions we specify: this results in something of a distorted image!

In comparison, setting xMidYMax slice tells our viewBox to scale our graphic; we align the smallest value of our viewBox (point zero) with the smallest value of our viewport. The key here is the use of meet – this tells the viewBox to scale up to, but not over the edge: in other words, “Align the image to be horizontally centered, but push it towards the bottom edge of our view box.”

Our third and final example takes a different tack – this time, our viewBox does not have a uniform size; it follows the same principle of alignment as our second example. This time though, we’ve set our second attribute to slice – this scales the SVG to the point that no empty space is left; it makes it look like we’ve really zoomed in on our image! If we were using standard CSS, then the equivalent would be background-size: cover.

Okay – time for a change of subject: as a developer, I’m sure you will be familiar with the need to make content available on multiple devices, right? We live in an age where more people access the Internet through devices other than a standard desktop PC; this will only increase over time!

At this point, I’m sure you will be asking what does this mean for SVG images – how easy is it to make an image responsive? Thankfully it is easy enough to do, and in fact we can use many of the same principles we might use for other content. Let’s take a moment to explore what is required in more detail.

Making SVG Content Responsive

Just over 20 years ago, when I first started using Windows PCs, I’d have never imagined browsing the Web from anything other than a standard PC – granted, that might later have included Apple Macs, but a PC is still a PC!

Today, it’s possible to view web-based content over dozens of different devices, from the humble smartphone through iPads, gaming consoles and of course standard PCs. This makes it harder for us developers, as we need to ensure our content is available on multiple devices; this does include how much (if it is not core to a strategy for mobile use for our site, for example, then why display it?)

Leaving aside the vulgarities of what should and should not be displayed, making an SVG graphic responsive is very easy – there are three some simple steps we can take:
  1. 1.

    Optimize our code – this should be treated as a given for every SVG we work with, but in many cases optimizing it will remove many of the elements that make an image non-responsive!

     
  2. 2.
    Add a preserveAspectRatio attribute and a class as a minimum – you may prefer to also surround the <svg> block in a <div>, although this isn’t always necessary:
    <div class="container">
      <svg version="1.1" viewBox="0 0 500 500"
    preserveAspectRatio="xMinYMin meet" class="content">
        ...
        </svg>
    </div>
     
  3. 3.
    Add in a CSS style rule for your content class (and container class, if you’ve used one) – the container code should look something like this:
    .container { display: inline-block; position: relative;
      width: 100%; padding-bottom: 100%; vertical-align: middle;
      overflow: hidden; }
    …and for the content, we can use this:
    .content { display: inline-block; position: absolute; top: 0;
      left: 0; }
     

The key to making it work is to use percentage values where possible – in many cases this is sufficient to make our image responsive, although we may need to use media queries for edge cases which have to be treated differently (more on this in a moment).

In our (theoretical) example, not only would our SVG graphic be responsive as an element, but the content within too – we’ve used padding in our case to ensure our content is correctly positioned, in a similar fashion to making responsive videos.

Adding code isn’t the only thing we need to do though – to create really effective responsive SVG, there are a number of steps we should follow. I’ve termed these the Golden Rules – this makes them sound a little formal, but they are really meant as guidelines to help you get the best out of your responsive SVG images. Let’s take a look at them in more detail, beginning with the setup of your tools.

Introducing the Golden Rules

If there is one thing in life I’ve leared, it is never to be too prescriptive – there are frequently times when flexibility is very much the order of the day! With that in mind , the following shouldn’t be interpreted as gospel, but more as a “checklist of inspiration” – something to help encourage optimal development:
  • Make sure you set your tools up correctly – this is where diligence can really pay off! It’s not something we’ve gone into detail, but I would recommend checking the following:
    • Consider using unitless values where possible, such as percentages; this helps to define proportional sizes, rather than specifying absolute values such as pixels. Pixels, ems and rems will work but can cause issues with accessibility, and don’t always display consistently across different devices.

    • Make sure your canvas is not set too big, with lots of empty space. Do allow some for anti-aliasing, if you want the edges of your SVGs to blend smoothly into the background (this will add extra pixels, to reduce the effect of sharp edges).

    • If you are using decimal precision, then two places is sufficient; anything larger will add bloat to our code and increase file sizes.

    • Try to use as few points as possible – this will provide greater control over the element, and keep file sizes down.

  • Remove any height and width attributes – many vector applications will add a lot of unnecessary code when exporting SVG images. In most cases, all we need at the start of our SVG files is the following, assuming a 500px by 500px viewBox is sufficient for your needs:
    <svg xmlns:="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
    <!-- SVG code here -->
    </svg>
  • Absolutely make sure your SVG code is at least optimized, if not also minified – this can typically save anywhere from 20 to 80 per cent in our file size, so it is absolutely worth the effort!

  • Where necessary, make sure you test your SVG images and code in IE9-11. SVG files (added using img tags) do not scale properly in these browsers, when viewBox, width and height values have been set. A quick fix is to take out height and width values from your SVG, and manipulate it using CSS only – you can see an example of how at https://stackoverflow.com/a/27971005 .

  • Consider using SVG for text within a banner – standard text can indeed be used, but SVG text has the added benefit of resizing automatically.

  • Use vector effects to keep hairlines thin – when working with SVGs, we can use stroke-width to set the thickness of lines. It is possible they might increase, depending on the size of the drawing; we can set vector-effect to prevent this from happening:
    path {
      ...
      stroke-width: 2;
      vector-effect: non-scaling-stroke;
    }
  • Don’t forget that we can embed other image formats within our SVG elements, such as JPEG, BMP, or even WebP. As long as we’ve followed the rules outlined so far, then these will become responsive if they have been added using the <image> tag.

  • Any media queries you create for manipulating the contents of your SVG should be stored within the SVG itself; SVG can only see these queries, when stored internally. If however the media query relates to positioning on the page, or whether it is displayed or hidden, then this can be applied to the container and stored externally.

  • There is a risk that at extremes our image may appear very small on a large canvas – try scaling up the image to fill the space, and avoid the need for extra code to fix the issue!

Ouch – it looks a little scary, but many of these guidelines can be automated: for example, we can use Node.js to automate tasks such as optimizing and minifying our code. These guidelines are not just about pure coding, but also about the creative thought and testing processes – after all, there’s more to just producing code, right?

Okay – let’s move on: time, I think, for a demo! We’ve talked a lot about how to make images responsive, so why not put this into action and see what it looks like in practice? With that in mind, let’s take a standard image and run through the steps to make it responsive, before applying media queries to help make our image truly responsive.

Updating SVG Images

For our next exercise, we’ll use a standard SVG image  – this time it will be of my favorite drinks, coffee! Yes, I’m sure this will be something many developers can relate to – long nights of coding, regular bouts of caffeine to keep going…not healthy I know, but sometimes needs must…

But I digress – we’ll use an SVG from the openclipart.org site; our one can be found at https://openclipart.org/detail/293550/coffee-to-go . I’ve already included a copy in the code download; please feel free to substitute if you want to use a different image.

MAKING IMAGES RESPONSIVE

Okay – let’s make a start:
  1. 1.

    We’ll start by downloading a copy of the responsive folder from the code download that accompanies this book – go ahead and store this at the root of our project folder.

     
  2. 2.

    Next, we need to optimize our SVG file – for this, go ahead and browse to https://jakearchibald.github.io/svgomg/  – this is the online SVGO optimizer tool we’ve already used earlier in this book. Drag and drop a copy of the coffee-to-go.svg, that is in the img folder from step 1, onto this page – this will automatically optimize the image for us.

     
  3. 3.

    Save the optimized image as coffee.svg into the img folder – we need the contents of that file shortly.

     
  4. 4.

    Go ahead and open up a copy of the responsive.html file from within the folder we stored back in step 1 – you will see a blank line at line 10.

     
  5. 5.

    We also need to open a copy of the coffee.svg file we’ve just saved, in our text editor – copy and paste the contents of that file into line 10 of responsive.html.

     
  6. 6.

    We’re almost there – there is one change we need to make to this content. Find this line:

    <svg xmlns:="http://www.w3.org/2000/svg" width="157" height="211">
    …and replace it with this:
    <svg version="1.1" viewBox="0 0 300 500" preserveAspectRatio="xMinYMin meet" class="content">

    …this adds a class which we make use of, sets the SVG to maintain an aspect ratio, and removes static size values.

     

You can see a finished version of the markup in the code download – it’s stored as responsive – finished version.html.

  1. 7.
    Save the file – if we preview the results in a browser, we’ll see something akin to the screenshot shown in Figure 4-8, when resized smaller.
    ../images/461821_1_En_4_Chapter/461821_1_En_4_Fig8_HTML.jpg
    Figure 4-8

    Our responsive SVG image

     

Go ahead and try resizing your browser window – what happens? Hopefully you will see that the image resizes automatically, without any loss of quality. The key here is that we’ve used the code we outlined in “Making SVG Content Responsive”; this proves that it is very easy to resize a basic SVG image. Granted, it might not work for some images, but it should be enough to cater for most standard SVG images.

Take a look at the CSS file used for this demo – you will see some of the code commented out. This is with good reason: you may find occasions when we don’t need to specify all of the code we used earlier, and that you can get away with just the attributes that have not been commented out.

Okay – what’s next, I wonder? We’ve touched on the basics of making images responsive, but there may be occasions when we find that simply adding max-width values isn’t enough. This might be for images that become unreadable on small screens, or where it isn’t necessary to display some content on particular devices. This is a perfect opportunity to use media queries, so let’s dive in and take a look at how we can set these up to work with SVG images in more detail.

Using Media Queries with SVG Content

Creating content that responds to a particular device can be a real minefield – there are so many decisions to make! What do we display? Do we hide X, and show Y instead…?

With standard formats such as JPEG or PNG, it’s simply a case of showing or hiding them, or perhaps resizing them to allow for the change in size of their location. But with SVG, this opens up some real possibilities – instead of changing the whole image, how about affecting a part of it? Yes, you heard me right – it’s easy to do, and adds a degree of flexibility to what we can achieve. It’s a perfect opportunity for a quick demo, so let’s dive in and see how easy it is to remove elements from an SVG image.

APPLYING MEDIA QUERIES TO SVG IMAGES

Let’s get cracking:
  1. 1.

    We’ll start by extracting a copy of the media folder from the code download that accompanies this book – it contains our markup, semi-prepared for our demo.

     
  2. 2.

    Open up the file media.html, then look for this comment, on or around line 28:

    <!-- label and badge on sleeve -->
     
  3. 3.

    Go ahead and edit the next two path statements – we need to add in IDs, as highlighted, which we will reference within our media queries:

    <path fill="#EDF1F9" id="badge" d="M80 ... />
    ...
    <path fill="#014463" id=”label" ... />
     
  4. 4.
    Save the file, then preview the results in a browser – if we resize the browser window to its smallest width, we will see the badge and label on the sleeve disappear, as shown on the left in Figure 4-9.
    ../images/461821_1_En_4_Chapter/461821_1_En_4_Fig9_HTML.jpg
    Figure 4-9

    Applying a media query

     

See how easy that was? All we’re doing is applying a technique that will be familiar to anyone who has developed responsive sites before; the trick (if anything) is where to apply the media query. As we’ve seen in our demo, the query must be inside the SVG; placing it outside might make better sense from an architectural perspective, but this is one of those occasions where we’re obliged to keep the rules within the SVG!

There is indeed a benefit to this approach – as media queries have to be stored internally, they will only ever react to the viewport of the image, not of the browser; it means that we can control how images look, independently of how they will be used.

In this instance, we’ve added in a simple style sheet inline – notice that it is encapsulated in <defs> tags; these definition tags help identify entries that are then applied to the core part of our code:
<defs>
 <style>
  @media all and (max-width: 300px) {
   #sleeve { opacity: 0; }
   #badge { opacity: 0; }
  }
 </style>
</defs>

The code within these <defs> tags is just standard media query code, to hide the two elements identified earlier in our code.

Understanding the Pitfalls

Up until now, I’ve painted what might seem a rosy picture – in that all we need to do is add a little code, and that all will be well, right...?

Well, if truth be told, making SVG images responsive isn’t always as easy as it might look – there are some pitfalls we should be aware of, when adding responsive capabilities to SVG graphics; some of these include the following:
  • Specifying fixed values for dimensions will clearly prevent our SVG from scaling – removing them is a must, but we might have to use the padding-bottom hack to ensure images are correctly displayed (in a similar fashion to responsive videos).

  • Testing is a must – most browsers will display SVG images correctly, but IE always likes to play the odd one in the pack, so to speak!

  • Planning what changes to make and when is essential – there is a temptation to work on desktop first, when mobile devices should be given preference. This will depend on the use cases for your project, so don’t assume desktop should always take priority!

  • Sprites can be used, but this requires two separate files: SVG and CSS, so what we gain from using sprites in a responsive capacity, is cancelled out by using multiple external resources.

  • There is a question around portability between different platforms when working responsively. Traditionally we may have simply hidden or displayed images based on the available screen width, but this is very limiting. Instead, we can easily manipulate individual elements of a SVG graphic, and this is a more efficient means.

  • Although we can set our own presentation attributes within a SVG file, these can be overridden by style declarations from outside of our SVG, such as in external style sheets.

In many cases, it would seem that the 80:20 rule would apply, but in reverse – the easy (20%) part is to add the code, but the harder, “bigger picture” part is making sure our site works as we expect!

Let’s change tack – we’ve almost reached the end of our journey through scaling SVG, but I want to leave you with some parting comments on one particular subject: Do we make our images responsive, or adaptive? Is there a right or wrong answer, or is it just a case of choosing one we prefer…?

Making SVG images Adaptive or Responsive ?

Do I make my image responsive…? Adaptive…? What’s the difference…?

Making images responsive can be a double-edged sword – while the code required can be very easy to implement, I’ll bet there are still questions being asked as to how images should be made “responsive” in the first place, right?

In truth, there are lots of different options we could use – many date from some years ago, and have either fallen out of favor, or been superseded by techniques that are cleaner and simpler to implement. This isn’t helped by some of the terms that we may hear – it can get very confusing!

To start with, you might have heard of the phrase “adaptive” – what does that mean, and how does it differ? Well, if you were referring to standard images, it’s about caching various sizes of an image, then serving the most appropriate size based on the detected screen size in use. This method relies on server-side code, which isn’t ideal – it’s a dated approach, and there are definitely better alternatives available. But – some people may treat the adaptive approach as referring to the use of media queries, which is a perfectly valid approach: perhaps you can understand why it might seem confusing! This isn’t helped by the fact that we can nest SVG images inside each other – not only is our main SVG now responsive, but the ones inside will also be too…

To really add to the mix, we can use a fluid approach – this is similar to responsive, but we instead calculate what proportion of screen estate an image should use. With the responsive approach, we will likely set a value such as max-width: 100%; with fluid, we will calculate the percentage to use, based on the width of an image as a percentage value of our document. Let’s say we have a 400px wide image, in a document that is 950px wide. The calculation would be:
(430 / 950px) x 100 = 45.26% (rounded to 2 pixels)

If we use this approach, we may need to set a max-width value to be sure that our image remains visible at extremes, but our image will always remain in scale with the rest of our document.

There is no one single right or wrong answer to solving this conundrum – the easy answer is that it will depend on individual circumstances. The technology is such now that we should not need to rely on server-side solutions to display images; we can use markup such as <picture> and the srcset attribute to render the appropriate image for the desired screen width. This should remove the need for media queries for all browser except IE; for this browser, we can use a polyfill such as Scott Jehl’s picturefill library, available at http://scottjehl.github.io/picturefill/ .

As a good starting point though, we can specify percentage values in place of static sizes; this will cover most scenarios, although there may be occasions where a more complex solution is required. Part of what we do will depend on which browsers we support – it may be a case of using the <picture> element, which does support a form of media query; I personally think this approach is cleaner than using media queries, but that is just personal preference! Whichever route we decide to use, I think that old adage of “test, test and test again” is so apt – any method we use should be tested to ensure maximum compatibility for the browsers we choose to support when using our site.

Summary

Scaling SVG content is a useful skill to master, along with making it responsive – many of the tricks we can use work in a similar fashion to CSS, although there are some key differences: enough to keep us on our toes. We’ve covered a lot of useful content in this chapter, so let’s take a moment to review what we’ve learned.

We kicked off with a quick introduction into scalability within the world of SVG, before moving onto exploring the SVG coordinate system, and how to apply it to SVG graphics. We then moved onto cover the Scaling Toolbox, before putting it to good use in a quick demo.

Next up came a brief journey through the steps needed to make SVG content responsive – we covered the basic principles of using CSS, before taking a look at how media queries can be used to manipulate more complex content. We then rounded out our journey through the world of scaling with a look at some of the pitfalls of making SVGs responsive, and covered some of the wider thoughts on how we might make our content responsive, or whether an adaptive approach might suit our needs.

Phew – onwards we go: there is never any rest for the wicked, I always say! Thankfully our next stop on this whistle-stop tour of SVG is one of my favorites: How many times have you played with filters in applications such as Photoshop? Well – that time may be coming to an end, as we can achieve a great deal within the browser, without the need for big heavyweights such as Photoshop – turn the page over if you want to learn more!

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

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