HTML & SVG — How to Draw with SVG?

Sherry Li
12 min readJan 20, 2023

--

The HTML <svg> tag could be used to draw various shapes and text. In this article, we will go through how to draw with SVG.

🇨🇳 To read this article in Chinese, please visit my Zhihu. 文章的中文版请戳我的知乎

1. Basics of SVG

1.1 What is SVG?

Scalable Vector Graphics (SVG) is an XML-based markup language for describing two-dimensional based vector graphics.

SVG images and their related behaviors are defined in XML text files, which means they can be searched, indexed, scripted, and compressed. Additionally, this means they can be created and edited with any text editor or with drawing software.

Compared to classic bitmapped image formats such as JPEG or PNG, SVG-format vector images can be rendered at any size without loss of quality and can be easily localized by updating the text within them, without the need of a graphical editor to do so.

🔍 1.2 HTML <svg> Tag

The <svg> tag defines a new coordinate system that acts as a container to draw everything inside.

Some common attributes we define for an <svg> element are:

  1. width: The width attribute is the displayed width of the rectangular viewport. Note that we need to define the value of the width as a percentage value or a number followed by a unit.
  2. height: The height attribute is the displayed height of the rectangular viewport. Note that we need to define the value of the height as a percentage value or a number followed by a unit.
  3. viewBox: The viewBox attribute is the SVG viewport coordinates for the current SVG fragment. The value of the viewBox attribute is a list of 4 numbers: min-x, min-y, width and height, separated by whitespace, where min-x and min-y represent the top left coordinates of the SVG viewport, and width and height represent its dimensions.
<!-- Create a 100px wide and 200px height SVG container, inside the container, we can define the x-coordinate from 0 to 200, and the y-coordinate from 0 to 400 -->
<svg
width="100px"
height="200px"
viewBox="0 0 200 400"
>
</svg>

You could visit MDN — <svg> to get a more complete understanding of the <svg> tag.

🔍 1.3 SVG Grid

As we create a <svg> element, the container size is defined by the width and height attributes (in various length units). Normally 1 user unit on the SVG grid equals to 1 screen unit, but if we define the viewBox attribute, then the user unit will be scaled by the width and height values we define in the viewBox attribute. By default, the origin of the SVG grid is positioned in the top left corner at coordinate (0, 0), but if we define the viewBox attribute, then the origin is positioned at coordinate (min-x, min-y).

📃 References

📌 https://developer.mozilla.org/en-US/docs/Web/SVG

📌 https://en.wikipedia.org/wiki/SVG

📌 https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Positions

📐 2. Drawing Shapes

2.1 Drawing Rectangles

The <rect> tag creates a width wide and height high rectangle at coordinate (x, y) with rounded corners defined by x radius rx and y radius ry.

<svg width="100px" height="100px">
<!-- A 30 wide and 80 high rectangle, where its top left corner is at (15, 10), and it has rounded corners with 5 x radius and 15 y radius -->
<rect x="15" y="10" width="30" height="80" rx="5" ry="15" />

<!-- A 25 wide and 80 high rectangle, where its top left corner is at (60, 10) -->
<rect x="60" y="10" width="25" height="80" />
</svg>

You could visit MDN — <rect> to get a more complete understanding of the <rect> tag.

2.2 Drawing Circles

The <circle> tag creates a circle centered at coordinate (cx, cy) with radius r.

<svg width="100px" height="100px">
<!-- A circle centered at (50, 50) with radius 20 -->
<circle cx="50" cy="50" r="20" />
</svg>

You could visit MDN — <circle> to get a more complete understanding of the <circle> tag.

2.3 Drawing Ellipses

The <ellipse> tag creates an ellipse centered at coordinate (cx, cy) with x radius rx and y radius ry.

<svg width="100px" height="100px">
<!-- An ellipse centered at (50, 50) with x radius 20 and y radius 40 -->
<ellipse cx="50" cy="50" rx="20" ry="40" />
</svg>

You could visit MDN — <ellipse> to get a more complete understanding of the <ellipse> tag.

2.4 Drawing Lines

The <line> tag creates a straight line between the point (x1, y1) and the point (x2, y2) with the color defined in the stroke attribute.

⚠️ Note: If we do not specify the stroke attribute, the line is not visible.

<svg width="100px" height="100px">
<line x1="50" y1="10" x2="10" y2="90" stroke="black" />
<line x1="50" y1="10" x2="90" y2="90" stroke="black" />
<line x1="0" y1="40" x2="90" y2="90" stroke="black" />
<line x1="0" y1="40" x2="100" y2="40" stroke="black" />
<line x1="100" y1="40" x2="10" y2="90" stroke="black" />
</svg>

You could visit MDN — <line> to get a more complete understanding of the <line> tag.

2.5 Drawing Polylines

The <polyline> tag creates a group of connected lines connecting the points defined in the points attribute. The value of the points attribute could be written as x1,y1 x2,y2 ... xn,yn .

Typically a polyline is used to create open shapes as the last point doesn't have to be connected to the first point.

<svg width="100px" height="100px">
<polyline
points="10,90 50,10 90,90 0,40 100,40"
stroke="green"
stroke-width="3"
/>
</svg>

You could visit MDN — <polyline> to get a more complete understanding of the <polyline> tag.

2.6 Drawing Polygons

The <polygon> tag creates a group of connected lines connecting the points defined in the points attribute. The value of the points attribute could be written as x1,y1 x2,y2 ... xn,yn .

Typically a polygon is used to create closed shapes as the last point is connected to the first point.

<svg width="100px" height="100px">
<polygon
points="10,90 50,10 90,90 0,40 100,40"
stroke="green"
stroke-width="3"
/>
</svg>

You could visit MDN — <polygon> to get a more complete understanding of the <polygon> tag.

2.7 Drawing Paths

The <path> tag could be used to create any shape or curve by defining a list of path commands in the d attribute.

Some common path commands are:

  1. Move To M x,y : Move the current point to the coordinate (x, y).
  2. Line To L x,y: Draw a line from the current point to the end point (x, y).
  3. Quadratic Bézier Curve Q x1,y1 x,y : Draw a quadratic Bézier curve from the current point to the end point (x, y), where the control point is at (x1, y1).
  4. Cubic Bézier Curve C x1,y1 x2,y2 x,y: Draw a cubic Bézier curve from the current point to the end point (x, y), where the start control point is at (x1, y1) and the end control point is at (x2, y2).
  5. Elliptical Arc Curve A rx,ry angle,large-arc-flag,sweep-flag x,y : Draw an arc curve from the current point to the end point (x, y), with x radius rx , y radius ry, and angle degrees rotation. The large-arc-flag allows to choose one of the large arc (1) or small arc (0), and the sweep-flag allows to choose one of the clockwise turning arc (1) or counterclockwise turning arc (0).
  6. Close Path Z or z : Close the current subpath by connecting the last point of the path with its initial path. If the two points are at different coordinates, a straight line is drawn between those two points.

For a complete list of path commands, you could visit MDN — d: Path Commands and MDN — Paths.

<svg width="100px" height="100px">
<!--
1. Move to (10, 30). Now the current point is at (10, 30).
2. Draw a clockwise turning arc from (10, 30) to (50, 30) with x radius 20 and y radius 20. Now the current point is at (50, 30).
3. Draw a clockwise turning arc from (50, 30) to (90, 30) with x radius 20 and y radius 20. Now the current point is at (90, 30).
4. Draw a quadratic Bézier curve from (50, 30) to (50, 90), where the control point is at (90, 60). Now the current point is at (50, 90).
5. Draw a quadratic Bézier curve from (50, 90) to (10, 30), where the control point is at (10, 60). Now the current point is back to (10, 30).
6. Close the path.
-->
<path
d="M 10,30
A 20,20 0,0,1 50,30
A 20,20 0,0,1 90,30
Q 90,60 50,90
Q 10,60 10,30
z"
/>
</svg>

You could visit MDN — <path> and MDN — Paths to get a more complete understanding of the <path> tag.

🔠 3. Drawing Text

🖋️ 3.1 Drawing Text

To draw text with SVG, we could use the <text> and <tspan> tags.

  1. <text>: The <text> tag draws a graphics element consisting of text.
  2. <tspan>: The <tspan> tag defines a subtext within a <text> or <tspan> element.
<svg width="100px" height="100px">
<text x="10" y="20">
Hello <tspan x="50" y="50">World</tspan>
</text>
</svg>

You could visit MDN — <text> and MDN — <tspan> to get a more complete understanding of the <text> and <tspan> tags.

🖍️ 3.2 Styling Text

The <textPath> tag could render text along the shape of a <path> element by enclosing the text within the <textPath> element with a href attribute referring to the <path> element.

<svg width="100px" height="100px">
<defs>
<path id="text-path" d="M 20,20 C 40,60 60,40 80,20" />
</defs>

<text>
<textPath href="#text-path">
Hello World
</textPath>
</text>
</svg>

You could visit MDN — <textPath> to get a more complete understanding of the <textPath> tag.

There are also properties we can set as an attribute or via a CSS declaration to change the styles of fonts. Here are some common attributes we set:

  1. font-family: The font-family attribute indicates which font family will be used.
  2. font-style: The font-style attribute specifies whether the text is to be rendered using a normal, italic , or oblique face.
  3. font-weight: The font-weight attribute refers to the boldness or lightness of the glyphs.
  4. font-size: The font-size attribute sets the size of the font.
  5. text-decoration: The text-decoration attribute defines whether text is decorated with an underline, overline, and/or line-through.
<svg width="100px" height="100px">
<text x="5" y="40" font-family="Helvetica">
Hello <tspan font-size="20" text-decoration="underline">World</tspan>
</text>
</svg>

🎨 4. Styling Drawings

4.1 Fills and Strokes

Fill attributes set the style inside an SVG object. Some common attributes are:

  1. fill: The fill attribute defines the color/gradient/pattern used to paint an SVG element.
  2. fill-opacity : The fill-opacity attribute defines the opacity of the paint server.
<svg width="100px" height="100px">
<!-- Left rectangle -->
<rect x="10" y="10" width="20" height="80" fill="blue" />

<!-- Middle rectangle -->
<rect x="40" y="10" width="20" height="80" fill="blue" fill-opacity="0.5" />

<!-- Right rectangle -->
<rect x="70" y="10" width="20" height="80" fill="rgba(0, 0, 255, 0.1)" />
</svg>

Stroke attributes set the style of the line drawn around an SVG object. Some common attributes are:

  1. stroke: The stroke attribute defines the color/gradient/pattern used to paint the outline of an SVG element.
  2. stroke-opacity: The stroke-opacity attrobute defines the opacity of the paint server applied to the stroke of the SVG element.
  3. stroke-width : The stroke-width attribute defines the width of the stroke to be applied to the SVG element.
  4. stroke-dasharray: The stroke-dasharray attribute defines a list of numbers separated by commas and/or whitespace that specifies the lengths of alternating dashes and gaps.
<svg width="100px" height="100px">
<!-- Top-left circle -->
<circle cx="25" cy="25" r="20" stroke="orange" />

<!-- Top-right circle -->
<circle cx="75" cy="25" r="20" stroke="orange" stroke-width="3" />

<!-- Bottom-left circle -->
<circle cx="25" cy="75" r="20" stroke="orange" stroke-opacity="0.5" stroke-width="5" />

<!-- Bottom-right circle -->
<circle cx="75" cy="75" r="20" stroke="orange" stroke-width="5" stroke-dasharray="1 3 5" />
</svg>

You could visit MDN — Fills and Strokes to get a more complete understanding of how to apply fill and stroke attributes.

4.2 Gradients

Within a <defs> section, we can define gradient objects such that any fill or stroke attribute could refer to those objects to apply gradients to paint SVG elements.

The two types of gradients are:

  1. Linear Gradient <linearGradient>
  2. Radial Gradient <radialGradient>

Within a gradient element, we can define several <stop> elements to specify the color stop-color and position offset to use on the gradient.

<svg width="100px" height="100px">
<defs>
<linearGradient id="linear-gradient">
<stop offset="0%" stop-color="orange" />
<stop offset="25%" stop-color="yellow" />
<stop offset="50%" stop-color="red" />
<stop offset="75%" stop-color="pink" />
<stop offset="100%" stop-color="gold" />
</linearGradient>

<radialGradient id="radial-gradient" cx="25%" cy="75%" r="75%" spreadMethod="repeat">
<stop offset="0%" stop-color="lightblue" />
<stop offset="50%" stop-color="blue" />
<stop offset="100%" stop-color="darkblue" />
</radialGradient>
</defs>

<!-- Left rectangle -->
<rect x="10" y="10" width="30" height="80" stroke="url(#linear-gradient)" stroke-width="5" />

<!-- Right rectangle -->
<rect x="60" y="10" width="30" height="80" fill="url(#radial-gradient)" />
</svg>

You could visit MDN — Gradients in SVG, MDN — <linearGradient> and MDN — <radialGradient> to get a more complete understanding of the gradient elements.

4.3 Patterns

Within a <defs> section, we can use the <pattern> tag to define pattern objects such that any fill or stroke attribute could refer to those objects to apply patterns to paint SVG elements.

Some common attributes we use to define a <pattern> element are:

  1. width & height : The width and height of the pattern tile.
  2. viewBox: The viewBox attribute defines the bound of the SVG viewport for the pattern fragment.
  3. x & y: The x and y coordinate shift of the pattern tile.
<svg width="100px" height="100px">
<defs>
<pattern id="heart-pattern" width="20%" height="20%" viewBox="0,0,100,100" fill="red">
<path
d="M 10,30
A 20,20 0,0,1 50,30
A 20,20 0,0,1 90,30
Q 90,60 50,90
Q 10,60 10,30
z"
/>
</pattern>

<pattern id="star-pattern" viewBox="0,0,10,10" width="20%" height="20%" fill="gold">
<polygon points="0,0 2,5 0,10 5,8 10,10 8,5 10,0 5,2" />
</pattern>
</defs>

<!-- Left ellipse -->
<ellipse cx="25" cy="50" rx="20" ry="40" fill="url(#heart-pattern)" />

<!-- Right ellipse -->
<ellipse cx="75" cy="50" rx="20" ry="40" fill="url(#star-pattern)" />
</svg>

You could visit MDN — Patterns and MDN — <pattern> to get a more complete understanding of the <pattern> tag.

5. When to Use SVG?

5.1 Pros ✅ vs. Cons ❌

Pros ✅:

  1. Unlike standard images, SVG images are vector and do not lose quality when resized or zoomed in the browser. Raster formats like PNG and JPG become pixilated when resized. SVG graphics are resolution-independent.
  2. SVG is a W3C standard file format. As such, it works well with other open standard languages and technologies including CSS, JavaScript, CSS, and HTML. SVG-based images can be manipulated using JavaScript and CSS because they integrate into the DOM.
  3. SVG graphics can be animated using JavaScript and CSS.
  4. Compared to other formats, SVG images are very small in size.
  5. SVG graphics can be printed at any resolution without a loss in image quality.
  6. SVG graphics are indexed by search engines. Therefore, SVG images are good for SEO (Search Engine Optimization) purposes.
  7. Like other image formats, SVG files can be scripted and compressed.
  8. SVG graphics do not need any unnecessary HTTP requests. Because they are made up of XML and CSS, they do not need the browser to request an image from a server, as is being done for standard images.
  9. With just a text editor, we can create SVG graphics.

Cons ❌:

  1. The SVG format is great for 2D graphics like logos and icons but is not ideal for detailed pictures. SVG-based graphics can’t display as many details as standard image formats since they are rendered using points and paths instead of pixels
  2. Even though SVG has been around since 1999 and is supported by most modern browsers (both on desktop and mobile), it does not work on legacy browsers.

5.2 When to Use SVG?

Some common scenarios to use SVG are:

  1. Display vector logos, icons, and other geometric designs.
  2. Display graphics in multiple sizes, screens, and a variety of devices.
  3. Display graphics that need to be updated and edited.

📃 References

📌 https://creatiffish.com/blog/other/svg-advantages-and-disadvantages/

7. SVG Libraries

There are also many SVG libraries you could import into your project.

  1. Snap.svg
  2. D3.js
  3. Feather
  4. SVGO
  5. Rough.js

--

--