Revised:

Content – SVG Structure

Accessibility and SVG

The images in the Hawkes Web Platform are primarily SVG images. From a content perspective there are several aspects of SVG that lend SVG to the creation of accessible images that are mathematically accurate, more so than traditional image formats, such as JPEG or PNG.

  1. The first aspect is the ability to create templates of visual objects using the defs element.
  2. The second aspect is being able to group together related portions of an image and use standard SVG markup to describe those groups.
  3. Third, text that is placed within an SVG image through use of the text element is readable, selectable, and able to be copied.
  4. Finally, SVGs are scalable and do not lose quality when enlarged, unlike other images like PNGs.

This provides enhanced accessibility for sight-impaired users and users in general. The W3C website provides a great example of the differences between PNG and SVGs here: SVG vs PNG Magnification. Each of these aspects is looked at in further detail in the rest of this document.

SVG Basics

There are several elements that make up an SVG. It is important to note that variations of this structure will occur based on the type of SVG being created. However, the basic structure of an SVG should appear in the following order:

<figure>
  <div>
    <svg>
      <title> </title> 
      <desc> </desc>
      <defs> </defs> 
      <g aria-hidden="true">  
        <g (as needed)>
        <paths> 
        <text> </text>  
        </g>  
      </g> 
    </svg> 
  </div> 
 <figcaption> </figcaption>
</figure>

For consistency we need to ensure that all of these pieces are present in the correct order and they also are used correctly in the context of specific SVGs. Starting at the top of the SVG structure we will look at each element and discuss its function beginning with the figure element.

Figure Element

The figure tag is included around SVG’s that have figure captions above or below. The tag goes around the div tag and also around the entire SVG. Depending on where the figcaption occurs in the text, it should be placed above or below the SVG but ALWAYS outside the div (if applicable) and svg tags but inside the figure tag.

DIV Element

The div tag applies appropriate CSS styles for our SVGs and should wrap EVERY SVG. The only exception is when SVGs occur in a table. In this circumstance adding a div around SVG’s within a table will cause display issues. For this reason all SVG’s that are placed in tables should not have div tags. Additionally, because they don't have div tags they should be given a defined height and width to prevent display issues due to excessive scaling.

ieSVG Class

Used when SVG’s have no defined height and width. Not defining a height and width allows SVGs to scale in Internet Explorer in a similar manner natively supported by other browsers. This occurs mainly with cartesian graphs, pie charts and bar graphs/histograms. Although number lines fall into this category as well, we don't want to apply the ieSVG class to them because there will be an excessive amount of whitespace above and below the numberline. When using the class ieSVG it should be included in the div tag. If there is no defined height and width Internet Explorer will set arbitrary values of 150 pixels for each which results in tiny images. Using the ieSVG class will prevent this.

SVG Element

The svg tag is the beginning of the actual SVG. There are a number of different parameters you can add to the svg tag but the absolute minimum must include the namespaces and a viewbox.

Namespaces From W3C: XML namespaces provide a simple method for qualifying element and attribute names used in Extensible Markup Language documents by associating them with namespaces identified by URI references. The namespaces we will be using are:

              
              xmlns=http://www.w3.org/2000/svg
              xmlns:xlink=http://www.w3.org/1999/xlink
            

Viewbox

All SVG’s should have a viewbox regardless of type. The viewbox allows for more specification on how the SVG will be displayed on screen. By changing the values you can display all or part of an SVG. Altering the viewbox can also shrink or enlarge the SVG display. The viewbox has four parameters that are separated by spaces.

viewbox="minimum-x  minimum-y width height"

In general, the minimum values should be set to 0 and the width and height should be set to the height and width values of the SVG.

Height and Width

The height and width attributes determine the actual size of the SVG. All SVG’s should have a defined height and width with the exception of Cartesian graphs and number lines. Using height and width in conjunction with viewbox provides a lot of display utility. In general, both the height and width should be no smaller than 250px and no bigger than 520px. However in some fringe cases it is acceptable for one of the dimensions to be below this threshold as long as the other is within the desired parameters.

The barebones SVG tag will be:

  

<svg viewBox="0 0 520 520" xmlns=http://www.w3.org/2000/svg xmlns:xlink="http://www.w3.org/1999/xlink"> 
</svg>
      
      

SVG Canvas

The SVG canvas is slightly different from the cartesian canvas. The minimum (0, 0) values begin in the top left corner for both x and y values. The farther right on the canvas, the larger the x-value and the farther down, the higher the y-value. When creating SVGs it is important to include a slight margin around the edges of the SVG. The actual SVG should not touch the edges of the viewbox because this can cause display issues.

Title(title) and Description(desc)

The title element represents the title of the object and will appear as a tooltip. The title should only contain plain text (NO MathML). This includes mathematical equations. If math needs to be included it should be done using plaintext with the "^" character representing exponents like this:

  7x^3 + 5x + 3

The desc element represents an extended description of the SVG. title and desc elements can be thought of as the alt and longdesc attributes in HTML. Using titles and descriptions combined with the semantic grouping of elements assists in the development of mental models by users of assistive technologies. Below is an example of our coordinate system with title and desc elements added. We should note that we have left out the contents of the defs element since it is defined later. In addition, note that the contents of the title and desc elements are not rendered on the page. However they will be read by SR technologies.

Cartesian coordinate plane This is a standard Cartesian coordinate system with axes of equivalent lengths. x axis This x axis does not have units printed on it. y y axis This y axis does not have units printed on it. x
<div class="ieSVG">
  <svg viewBox="0 0 520 520" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <title>Cartesian coordinate plane</title> 
    <desc>This is a standard Cartesian coordinate system with axes of equivalent lengths.</desc>
  </svg>
</div>

Another benefit of SVGs is that MathML elements can be inserted into desc elements. Below is an example using MathML in the desc element to represent the equation of the line. In this way we can use the actual equation as a description of the shapes or lines that make up the visual representation of the equation.

Cartesian Graph and Equation Example The equation of the line is y = 2 x + 2 . Two of the points it passes through are ( 0 , 3 ) and ( 2 , 1 ) . X Axis x Y Axis y
              
<title>Cartesian Graph and Equation Example</title>
<desc>The equation of the line is
  <math>
    <mi>y</mi>
    <mo>=</mo>
    <mrow>
      <mrow>
        <mn>2</mn>
        <mo>&#x2062;</mo>
        <mi>x</mi>
      </mrow>
      <mo>+</mo>
      <mn>2</mn>
    </mrow>
  </math>. Two of the points it passes through are
  <math>
    <mo>(</mo>
    <mrow>
      <mn>0</mn>
      <mo>,</mo>
      <mn>3</mn>
    </mrow>
    <mo>)</mo>
  </math> and
  <math>
    <mo>(</mo>
    <mrow>
      <mrow>
        <mo>&#x2212;</mo>
        <mn>2</mn>
      </mrow>
      <mo>,</mo>
      <mrow>
        <mo>&#x2212;</mo>
        <mn>1</mn>
      </mrow>
    </mrow>
    <mo>)</mo>
  </math>.
</desc>
            
            

defs and use Elements

The defs Element

The defs element is used to define elements to be reused later in an SVG. Some elements, such as marker, can only exist within a defs element. Other SVG elements can exist within a defs and can be called with the use element. Below we define the different arrowhead markers that are used throughout the document. Since none of the elements within the defs are actually rendered on the page, there is nothing to show here but the code.


<svg width="250" height="250" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>Def Element Example</title>
  <desc>Brief introduction to definitions utilizing axis arrowhead markers. These markers are used in every cartesian graph and numberline SVG.</desc>
    <defs>
        <marker id="axisArrowheadStart" orient="auto" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7.5" markerHeight="7.5">
            <path class="fill" d="M10,0 L0,5 L10,10z" />
        </marker>
        <marker id="axisArrowheadEnd" orient="auto" viewBox="0 0 10 10" refX="0" refY="5" markerWidth="7.5" markerHeight="7.5">
            <path class="fill" d="M0,0 L10,5 L0,10z" />
        </marker>
    </defs>
</svg>
  
  

Elements that exist within a defs element can be replicated in other SVG images using a simple ID reference. This allows for the creation of image templates to ensure that SVG images are consistent without the need for scripting. This reduces page load times, while helping students to focus on learning.

An important note about defs is that they are not limited to a single SVG on the screen. Once definitions are included on the page they can be referenced by any SVG on that page. For learn screens with multiple SVGs we do not want to repeat the same definitions for each SVG. For these instances, include all of the defs in first SVG. If a subsequent SVG needs a more specific definition, it should be included within that SVG. This will reduce the amount of redundant code while clarifying which definitions each SVG uses.

The use Element

The use element allows you to duplicate and reuse previously created elements. Using the xlink:href attribute, the use element can reference a previously implemented grouping ID or definition. This is a great way to reduce the amount of code and save time. Height, width, and x / y attributes can be added to the use element for proper placement and sizing.

The examples below show multiple ways of combining the use and defs elements with other elements (like path) to create new images.

defs and use Example
Using DEF and USE elements Three uniquely colored arrows created using def and use elements. From top to bottom, the arrows are red blue and green. The red and blue arrows were created using only existing definitions while the green arrow was created from scratch but still utilized the marker attribute.

<defs>
  <marker id="arrowheadEnd1" orient="auto" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="7.5" markerHeight="7.5">
   <path class="primaryFill" d="M0,0 L10,5 L0,10z" />
  </marker>
  <marker id="arrowheadEnd2" orient="auto" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="7.5" markerHeight="7.5">
    <path class="secondaryFill1" d="M0,0 L10,5 L0,10z" />
  </marker>
  <marker id="arrowheadEnd3" orient="auto" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="7.5" markerHeight="7.5">
    <path class="secondaryFill2" d="M0,0 L10,5 L0,10z" />
  </marker>
  
  <path id="blueLine" class="line stroke2 primaryStroke" d="M0 0 h100" />
  <path id="redLine" class="line stroke2 secondaryStroke1" d="M0 0 h100" />
</defs>
<use xlink:href="#redLine" x="90" y="50" marker-end="url(#arrowheadEnd2)" />
  <use xlink:href="#blueLine" x="70" y="80" marker-end="url(#arrowheadEnd1)" />
  <path class="line stroke2 secondaryStroke2" d="M 50 110 h100" marker-end="url(#arrowheadEnd3)" />
              

The red and blue arrows were made exclusively by referencing the defs "blueLine" and "redLine" and the colored arrrowhead markers. The green line was created from scratch using the path element but also references the green arrowhead marker. Either option can create an accessible image but having a strong understanding of the use element will make the code more succint.

Grouping (g) Element

SVGs support the grouping of multiple SVG elements through the use of the g element. The g element can be used to group visual elements together that are semantically linked. It can also be used to group together elements that make up a distinct object but themselves are only pieces. The grouping of related elements can create a hierarchy within the SVG document that will allow users to create a mental model of the image.

Grouping semantic elements together helps organize the code within the SVG. For a Cartesian graph, we would group the Cartesian dot and its coordinates (x, y) together because they are semantically linked. We don’t want all the points in one group and all the coordinates in another.

There are two different ways to assign unique identifiers to grouping elements. If the grouping element is included in a defs tag we can assign it an ID attribute. This is done like so:

<g id="Insert_ID_Here">

Adding an ID attribute to the group provides an easy way to reference the group later on and, with proper naming, makes it easy to know what the group consists of. ID’s should not contain spaces, if they do it will throw an error in the W3C validator tool during the finalization process. If the grouping element is not contained within the defs then we can add a comment to the group for readability. This is done like so:

<g data-comment="Insert Comment Here">

Not all groups will require ID’s or comments but in situations with complicated SVG’s they are very beneficial. Each ID and comment should be a unique identifier. If they are not unique the page will not validate so avoid duplicates at all costs!

The example below provides a clear method of how to semantically group elements together in an effective way.

Grouping Example
Proper Grouping Example Graph of the equation y = x + 2 . There are four labeled points. Starting at the bottom left of the graph and moving up towards the top right the points are as follows: ( 4 , 4 ) , ( 2 , 0 ) , ( 1 , 3 ) and ( 4 , 6 )
              
  <g data-comment="Points and Coordinates">
    <g data-comment="point(1, 3)">
      <use xlink:href="#cartesianDot1" x="284" y="188" />
      <text class="svgMath" x="310" y="190">(1, 3)</text>
    </g>
    <g data-comment="point(4, 6)">
      <use xlink:href="#cartesianDot1" x="356" y="116" />
      <text text-anchor="end" class="svgMath" x="340" y="110">(4, 6)</text>
    </g>
    <g data-comment="point(-2, 0)">
      <use xlink:href="#cartesianDot1" x="212" y="260" />
      <text text-anchor="end" class="svgMath" x="220" y="240">(−2, 0)</text>
     </g>
    <g data-comment="point(-4, -2)">
      <circle class="secondaryFill1" cx="164" cy="308" r="8" />
      <text text-anchor="end" class="svgMath" x="150" y="310">(−4, −2)</text>
    </g>
  </g>
  
  

Each of the points on the graph and their respective coordinates are grouped together. This reinforces the idea that each point and its coordinates are linked. If we were to group all of the coordinates together in one group and all of the points in another group, this information would be lost.

Aria-hidden Grouping

Another important use for the grouping element is to apply the aria-hidden attribute to elements or groups of elements which contain text. If best practices are followed, the title and desc will provide all the relevant information about the SVG. If this holds, then all of the subsequent text in the SVG will be redundant. aria-hidden will prevent SR technologies from repeating information to students.

NOTE: The aria-hidden grouping should be included after the title, desc and defs tags and not at the beginning of the SVG. If the aria-hidden grouping wraps the title and desc then they will not be visible to SR technologies.

The example below shows how to properly implement the aria-hidden attribute.

Aria-Hidden Example
Aria-Hidden Example This example shows the setup for the long division of 63.86 divided by 6.2

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 250 250" height="250" width="250">
  <title>Aria-Hidden Example</title>
    <g aria-hidden="true">
      <g data-comment="Long Division">
        <text text-anchor="middle" class="svgMath" x="60" y="40" dy="0 0 0 0 -2">6.2 )</text>
        <path class="line stroke1" d="M 77.25 19 h77" />
        <text text-anchor="middle" class="svgMath" x="120" y="40">63.86</text>
      </g>
    </g>
</svg>

The path Element

The path element is used to draw lines and outline shapes within SVGs. There are a number of different attributes that a path can have. The data for the path is contained in the d attribute. The specifics for the d attribute can include moveto (M/m), lineto (L/l), horizontal line (H/h), vertical line (V/v), closepath (Z/z), and curve commands (for curve commands please refer to the SVG Pocket Guide). All of these path specific attributes may be used repeatedly (if necessary) within the path data.

Moveto (M/m)

The path data must begin with a moveto command. The moveto command creates a new point in the same way we lift a pen to a new point to begin drawing on a sheet of paper.

Closepath (Z/z)

Closepath ends the current subpath and draws a straight line from the initial point of the path to the current point being closed. For this attribute, "Z" and "z" are interchangeable. It is important to note that you can have additional subpaths in the path data after using closepath.

Line Commands

Lineto (L/l)

The lineto command has the most utility and draws a line from any one point to any other point. When chaining lineto commands together, the end point of the current line becomes the starting point of the next unless a moveto command is used.

Horizontal Line (H/h)

The horizontal line command draws a horizontal line from the current point to a specified point "x" pixels to the left or right

Vertical Line (V/v)

The vertical line command draws a vertical line from the current point to a specified point "y" pixels up or down.

Chaining Multiple Line Commands

Chaining multiple lines or curves into path data is how complex shapes are created. The two examples below highlight how to chain multiple lines together within the same path. The triangle image was created with only one moveTo command and each line was drawn from the end point of the previous line. The three diagonal lines were created within the same path but made use of the moveTo command to draw the next line at a new point.

Chaining Multiple Lines in a Path

<svg viewBox="0 0 250 250" height="250" width="250" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
  </defs>
  <g aria-hidden="true">
    <path class="line stroke2 noFill" d="M50 60 l 30 50 h-60 l 30 -50" />
    <path class="line stroke2 noFill" d="M150 60 l 30 50 M160 60 l 30 50 M170 60 l 30 50" />
  </g>
</svg>
  

Capital letters signify absolute positioning while lower case letters signify relative positioning. In most cases using relative positioning will be more beneficial than using absolute. Using relative positioning makes the code easier to refactor later if necessary.

This idea is expressed in the example below. The top triangles are the originals, with the left triangle created using relative positioning and the right with absolute. When the first triangle was shifted down, the only change required was to change the original moveTo y-value from 60 to 120. For the absolutely positioned triangle, every y-value in the path needed to be altered to keep the image intact. When working on complicated SVGs with large amounts of pathing data, altering an absolutely positioned SVG will get very complicated very fast.

Pathing: Absolute vs Relative Positioning

<svg viewBox="0 0 250 250" height="250" width="250" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
  </defs>
  <g aria-hidden="true">
    <g data-comment="Original Triangles">
      <path data-comment="Relatively Positioned Triangle (Top Left)" class="line stroke2 noFill" d="M50 60 l 30 50 h -60 l 30 -50" />
      <path data-comment="Absolutely Positioned Triangle (Top Right)" class="line stroke2 noFill" d="M150 60 L 180 110 H 180 120 L150 60 " />
    </g>
    <g data-comment="Position Altered Triangles">
      <path data-comment="Relatively Positioned Triangle (Bottom Left)" class="line stroke2 noFill" d="M50 120 l 30 50 h -60 l 30 -50" />
      <path data-comment="Absolutely Positioned Triangle (Bottom Right)" class="line stroke2 noFill" d="M150 120 L 180 170 H 180 120 L150 120 " />
    </g>
  </g>
</svg>
  

Text in SVG

An important part of SVG accessibility (and useful information in general) is that actual text can be used within SVG images, whereas text would be converted to a number of pixels in more standard image formats. Text can be placed within text elements and given x and y coordinates on the SVG canvas to be placed. Characters placed within text elements will be displayed on the screen as well as being read by assistive technology. If you have a title and description of a grouping of elements any characters within text elements will also be read unless they are specifically given the aria-hidden attribute set to "true". This should ALWAYS be done when an SVG contains text. The tspan element can be used within a text element to place the text in different places on the SVG canvas. The article Authoring Accessible SVGs gives an excellent explanation of how to use text and tspan elements to arrange text in an SVG but still provide the same information to users of assistive technologies.

Text-anchor element

The text-anchor attribute will determine the location of the x and y coordinates in relation to the text being placed on the SVG. This attribute should always be used, regardless of the text. One of three identifiers can be used: start, middle, and end. When placing text to the right of another element, start should be used. When placing text to the left of another element, end should be used. Only use middle if the text will be directly above or below the element you wish to label. These specific instances allow the font size of the text to grow while ensuring the element it is labeling will not be overlapped. The text-anchor attributes are listed below.

text-anchor="start"text-anchor="middle"text-anchor="end"

The example below outlines each different use case for the text-anchor attribute. The coordinates (−2, 1) and (2, −2) make use of the text-anchor="middle" attribute because they are directly above and below their respective points. The "Text1" text uses the text-anchor="end" attribute because it lies to the left of the line. The "Text2" text uses text-anchor="start" because it lies to the right of the line.

Text-Anchor Example
Text-Anchor Example Graph of y = x 3 . There are two points not on the equation of the line. They are ( 2 , 1 ) and ( 2 , 2 )

T-span Element

The tspan element can be used in a number of instances regarding text in SVGs. It is similar to the span tag in HTML. If you wish to style or move only a single character (or set of characters) within a text tag, tspan should be used with the appropriate classes and attributes. The attributes dx and dy can be used to move the value(s) in any direction, relative to the previous text. This can be useful when using exponents and degree symbols.

T-span Gotchas:

tspan preserves all white space within it. When using tspan ensure that the only spaces included are the ones needed. Otherwise it will cause display issues like the extra spaces in the whitespace error example below.

When using tspan to change the position of elements within a text element, it is important to remember that the position change of the tspan will apply to EVERYTHING after it within the same text element, not just what is included in the tspan. After using the tspan for a power or subscript you will need to readjust the dx and dy values to use the original baseline using an additional tspan. The examples below outline the correct tspan display and display issues associated with improper tspan use.

tspan Examples
Correct and incorrect use of tspan This SVG shows the correct and incorrect ways to implement tspan. The first example shows the proper way to use tspan. The second outlines what happens when there is extra whitespace in the text. The last example shows what happens when the baseline is not reset after using exponents.

<g data-comment="Correct tspan">
  <text x="150" y="30" text-anchor="end">Correct tspan:</text>
    <text class="svgMath primaryFill" text-anchor="start" x="170" y="30">2<tspan class="italic">x</tspan><tspan class="fontSmall" dy="-14">2</tspan><tspan dy="14"> + 4<tspan class="italic">x</tspan> + 5</tspan>
  </text>
</g>
<g data-comment="tspan excessive white space">
  <text x="150" y="90" text-anchor="end">Whitespace Error:</text>
  <text class="svgMath primaryFill" text-anchor="start" x="190" y="90">2<tspan class="italic"> x </tspan><tspan class="fontSmall" dy="-14"> 2 </tspan><tspan dy="14"> + 4 <tspan class="italic"> x </tspan> + 5</tspan>
  </text>
</g>
<g data-comment="tspan baseline error">
  <text x="150" y="150" text-anchor="end">Baseline Error:</text>
  <text class="svgMath primaryFill" text-anchor="start" x="190" y="150">2<tspan class="italic">x</tspan><tspan class="fontSmall" dy="-14">2</tspan>+ 4<tspan class="italic">x</tspan> + 5</text>
</g>
                    

Transformations

Elements occuring within an SVG can be transformed to be used in different situations then what might have been previously envisioned. When transforming an element the element will shift its position on the SVG canvas dependening on whether the x or y values are being transformed and by what factor they are being transformed by. Since placement of elements will be of the utmost importance in the WebProduct, understanding how to deal with transformed elements moving around on the canvas is important.

To use a transform on an object in an SVG, use the attribute transform="type of transform". The transformation can be translate, scale, rotate or skew. You can also use the transform matrix, but this requires understanding of the matrix system. There are examples of the basic transforms below, and you can learn more on the MDN Transform Page. For more guidance on the subject of view boxes, transformations and many other things SVG check out this article Soueidan's Blog: SVG Tranformations. Any transformation that is applied to an element in effect changes the coordinate system for that element. If you translate something, you are setting up a new coordinate system for the element, with the starting coordinates however far in the x and y directions that your transform specified.

Translate

The first transform to discuss is translate. In effect, translating an element means moving it. The code for this is:  transform="translate(x [y])".

This definition specifies a translation by x and y. If y is not provided, it is assumed to be zero. If you have a rect element that is drawn at x="10" and y="10", and transform it 100px to the right and 35px down, then you are in effect drawing the rect at x="110" and y="45". You can also translate groups of multiple elements so that the entire group is shifted rather than translating each individual element. This is particularly helpful when shifting fractions or large equations.

The example below outlines a basic transformation of a square.

Translate Example

<g aria-hidden="true">
  <g data-comment="Original Rectangle">
    <rect x="10" y="10" width="50" height="50" class="line noFill stroke1" />
    <text class="svgMath fontSmall" text-anchor="start" x="75" y="35">The rectangle before the translation</text>
  </g>
  <g data-comment="Translated Rectangle">
    <rect transform="translate(100,35)" x="10" y="10" width="50" height="50" class="secondaryStroke1 noFill stroke1" />
    <text class="svgMath fontSmall secondaryFill1" text-anchor="start" x="175" y="70">The rectangle after the translation</text>
  </g>
</g>

Scale

The second transformation is scale. The code for this is:  transform="scale(x [y])"

This definition specifies a translation by x and y. If y is not provided, it is assumed to be equivalent to x.

Keep in mind that when you use transform to scale an element, the scaling factors are applied to all of the positional numbers in the element. So if you have a rect element that you want to scale by 2, the x and y coordinates of the upper left hand corner of the rectangle will be multiplied by 2 and the height will be multiplied by 2. If your starting x and y coordinate values are 20, then your new coordinates after the transformation would be 40. Notice as well that the stroke width changes with the scaling.

If you want to keep the upper left hand corner of the rect element in the same spot you will need to move it up the difference between the old and new coordinate using translate. This translate can be placed in the same transform statement as the scale. See the examples below.

Scaling Example

<svg width="520" height="250" viewBox="0 0 520 250" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <g aria-hidden="true">
    <g data-comment="Original Rectangle">
      <rect x="20" y="20" width="50" height="50" class="line noFill stroke1" />
      <text class="svgMath fontSmall" text-anchor="start" x="85" y="35">The rectangle before scaling</text>
    </g>
    <g data-comment="Scaled Rectangle">
      <rect x="20" y="20" width="50" height="50" transform="scale(2)" class="secondaryStroke1 noFill stroke1" />
      <text class="svgMath fontSmall secondaryFill1" text-anchor="start" x="155" y="95">The rectangle after scaling</text>
    </g>
  </g>
</svg>
                
Scaling Plus Translating Example

<svg width="520" height="250" viewBox="0 0 520 250" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <g aria-hidden="true">
    <g data-comment="Original Rectangle">
      <rect x="20" y="20" width="50" height="50" class="gridline noFill stroke1" />
    </g>
    <g data-comment="Scaled Rectangle">
      <rect x="20" y="20" width="50" height="50" transform="scale(2)" class="secondaryStroke1 noFill stroke1" />
      <text class="svgMath fontSmall secondaryFill1" text-anchor="start" x="155" y="95">The rectangle after scaling, before translation.</text>
    </g>
    <g data-comment="Scaled and Translated Rectangle">
      <rect x="20" y="20" width="50" height="50" transform="scale(2) translate(-10,-10)" class="primaryStroke noFill stroke1" />
      <text class="svgMath fontSmall primaryFill" text-anchor="start" x="130" y="30">The rectangle after scaling and after translation.</text>
    </g>
  </g>
</svg>
              

Mirror Imaging

One really useful thing you can do with a combination of scale and translate is to mirror an object across the canvas of the SVG. This is particularly useful when drawing curves that are mirrored across an axis. To do this, you scale the element by −1 in the direction you want to mirror, then translate by the width of the canvas. See the example below.

Mirror Line Example
Mirror Image Example This SVG shows a line on the left side going straight down then curving towards the middle in an almost straight line. At the middle of the image there is a dashed line representing the point where the image is mirrored, then across that dashed line to the right is the reflection of the line on the left.

<g data-comment="Mirror Line (Dashed)">
  <path d="M250 0 v100" class="gridline stroke1 dashed" />
  <text class="svgMath fontSmall" x="250" y="115" text-anchor="middle">Mirror Line</text>
</g>
<g data-comment="Original Path">
  <path d="M10 60 C15 150 35 50 240 70" class="primaryStroke stroke2 noFill" />
</g>
<g data-comment="Mirrored Path">
  <path d="M10 60 C15 150 35 50 240 70" class="primaryStroke stroke2 noFill" transform="scale(-1,1) translate(-500 0)" />
</g>

Rotation

The next transformation is rotate. The code for this is:

transform="rotate(a [x y])"

This specifies a rotation by "a" degrees about a given point, which is defined by x and y. The "a" represents the degree of rotation and can be positive (clockwise) or negative (counter-clockwise). If x and y are not supplied, the rotation is about the origin of the current user coordinate system (default is the top left corner).

For an example, take a rect element and apply a rotate of 25 degrees without specifying the x and y coordinates. Notice that while the rect is rotated, it doesn't just rotate around itself. Instead, a copy of the canvas, the user coordinate system, is created and rotated by 25 degrees.

Rotation Example

<g data-comment="Original Rectangle">
  <rect x="250" y="10" width="50" height="50" class="line noFill stroke1" />
  <text class="svgMath fontSmall" x="240" y="40" text-anchor="end">The rectangle before rotation</text>
</g>
<g data-comment="Rotated Rectangle">
  <rect x="250" y="10" width="50" height="50" transform="rotate(25)" class="secondaryStroke1 noFill stroke1" />
  <text class="svgMath fontSmall secondaryFill1" x="275" y="155" text-anchor="start">The rectangle after rotation</text>
</g>              

However, if we specify the x and y coordinates as the center of our rect, we get a very different result like the blue rectangle below.

Rotation Example with x and y values

<g data-comment="Rotated Rectangle with x and y specified">
  <rect x="250" y="10" width="50" height="50" transform="rotate(25,275,35)" class="primaryStroke noFill stroke1" />
  <text class="svgMath fontSmall primaryFill" text-anchor="start" x="290" y="85">The rectangle after x/y rotation</text>
</g>

Skew

The final transformation is skew, but it is not particularly useful in creating SVGs for the WebProduct. The code for it is:

transform="skewX(a)" or transform="skewY(a)".

This defines a skew across the x or y axis by "a" degrees. Visual examples are provided below.

Skew X Axis

<g data-comment="Rectangle without skew">
  <rect x="10" y="10" height="50" width="75" class="stroke1 line noFill" />
  <text class="svgMath fontSmall" x="90" y="40" text-anchor="start">The rectangle before skewX</text>
</g>
<g data-comment="Rectangle with skew on X axis" transform="translate(-30, 0)">
  <rect transform="skewX(20)" x="10" y="90" height="50" width="75" class="stroke1 line secondaryStroke1 noFill" />
  <text x="135" y="120" text-anchor="start" class="svgMath fontSmall secondaryFill1">The rectangle after skewX</text>
</g>                
Skew Y Axis

<g data-comment="Rectangle without skew">
  <rect x="10" y="10" height="50" width="75" class="stroke1 line noFill" />
  <text class="svgMath fontSmall" x="90" y="40" text-anchor="start">The rectangle before skewY</text>
</g>
<g data-comment="Rectangle with skew on X axis">
  <rect transform="skewY(20)" x="10" y="90" height="50" width="75" class="stroke1 line secondaryStroke1 noFill" />
  <text x=90 y="150" text-anchor="start" class="secondaryFill1 svgMath fontSmall">The rectangle after skewY</text>
</g>
              

Resources