Scroll to top

In this tutorial we’re going to cover all the fundamentals of coding SVGs by hand, but I’m not going to bore you with a dry lecture that just trots out the relevant shapes and attributes. Instead you’ll learn how to hand code SVG through practice, creating six icons. In the process, you’ll use all of the basic elements required for SVG hand coding.

Our Hand-Coded SVG Icons

This is what you’ll be creating:

One of the great things about scalable vector graphics (aside from their being infinitely scalable without quality loss) is that once you know the fundamentals you can hand-code simple shapes quite easily, without needing to open a graphics application. 

With just a few lines of code you can have your own custom icons, and you’ll know exactly how each one is put together. When you create your own SVGs you ensure they are written in the most efficient way possible, and you have the maximum level of control when using them in your sites.

Basic SVG Elements

You can get into a lot of complexity with SVG, but that’s not necessary for the icons we’ll be making. The following list covers the building blocks we’ll need.

  • <svg> Wraps and defines the entire graphic. <svg> is to a scalable vector graphic what the <html> element is to a web page.
  • <line> Makes single straight lines.
  • <polyline> Makes multi-segment lines.
  • <rect> Makes rectangles and squares.
  • <ellipse> Makes circles and ovals.
  • <polygon> Makes straight sided shapes, with three sides or more.
  • <path> Makes any shape you like by defining points and the lines between them.
  • <defs> Defines reusable assets. Nothing placed inside this <defs> section is visible initially. <defs> is to a scalable vector graphic what the <head> element is to a web page.
  • <g> Wraps multiple shapes into a group. Place groups in the <defs> section to enable them to be reused.
  • <symbol> Like a group, but with some extra features. Typically placed in the <defs> section.
  • <use> Takes assets defined in the <defs> section and makes them visible in the SVG.

As we go through and create our icons, we’ll be working through this list of elements in the order seen above.

Starter Files

Before we get started, grab yourself a copy of the starter files from the GitHub repo. You can either download a .zip file, or clone the repo to your own system.

We’re going to begin with a document that has some basic HTML and CSS already in place. This will give some styling to the SVGs we’ll be making, and will also set you up with a little grid on the page. We’ll be creating our icons over the top of this grid, and hopefully it will help you visualize the coordinates you’re working with when laying down your SVGs. 

When you open up “handcodedsvg.html” from the source “Starter Files” folder you should see the following:

Quick Primer on x and y Values

When working in 2D space on a website, the horizontal axis is represented by x and the vertical axis is represented by y. Positions along each of these axes are represented by numbers. If we want to move something to the right, we’ll need to use increasing x values, and to move to the left we’ll use decreasing x values. Likewise, to move something down we’ll use increasing y values, and to move something up we’ll use decreasing y values.

A common shorthand for expressing the x and y values of a single point is (x, y). For example, a point at 10 on the x axis and 50 on the y axis might be written as (10, 50). I’ll use this shorthand from time to time in this tutorial.

Notice the two darkest lines on our grid? We’re going to place our SVG so its top left corner aligns with the place they intersect. As such, that intersection point will represent the position x = 0 and y = 0 , or (0,0), in our SVG.

The Background Grid

Each of the lightest grid lines represents 10px, and the medium thickness lines represent 100px. So if we wanted to move an object down from one medium thickness line to the next, we’d increase its location on the y axis by one 100px.

If that still sounds a little unclear, don’t worry this will all make sense as we get into the practicalities of creating our SVG icons.

Default SVG Styling

Note that in the starter HTML file there is some included CSS with default styling for our soon-to-be-created SVG icons:

1
svg {
2
  stroke: #000;
3
  stroke-width: 5;
4
  stroke-linecap: round;
5
  stroke-linejoin: round;
6
  fill: none;
7
}

This will set our icons to have no fills, and black 5px wide strokes with rounded caps and joins.

1. Setup the SVG

The first step in creating any SVG is to lay down an <svg></svg> element. Anything you want your SVG to display will have to be between these tags. There are a few attributes you can use on this element, but we’ll keep things simple and just use width and height.

Add the following code in the <body> section of your HTML document:

1
<svg width="750" height="500">
2
3
</svg>
The CSS in our starter file is going to offset this SVG down and to the right by 100px so its top left corner will be positioned at the intersection point of the two darkest lines on our background grid. And the values in the CodePen demos throughout this tutorial may differ slightly too–but feel free to play around with them.

2. Create “Left Align” Icon

Let’s start by using the <line> element to create this left align icon:

The line element has four attributes you’ll need to use:

  • x1 horizontal starting point of the line
  • y1 vertical starting point of the line
  • x2 horizontal ending point of the line
  • y2 vertical ending point of the line

To summarize the above, you use the x1 and y1 attributes to set where the line begins, and the x2 and y2 attributes to set where the line ends.

Let’s create the first line of our icon, the one at the top. We’re going to make the line 45px long, however the 5px stroke we’re using is going to add some extra pixels around the outside of our line. As such we’ll need to offset our line down and to the right by 3px to ensure none of the extra pixels created by the stroke are clipped off.

For that reason, we’re going to start our line at a position of 3 on the x axis and 3 on the y axis. We can set this line starting point of (3,3) by using the attributes x1="3" y1="3".

We want the line to be 45px long, so we’re going to add 45 to our starting x position of 3, giving us 48 as the value we want to set for x2. We want the line to finish at the same position on the horizontal axis, so we’ll set y2 to equal 3, i.e. the same value we gave to y1. We’ll add this (48,3) line ending point via the attributes x2="48" y2="3".

The complete code for the first line should look like this:

1
<line x1="3" y1="3" x2="48" y2="3"></line>

Check your browser preview and you should see a 45px long black line with nice rounded caps.

Now we can go ahead and add the next three lines to our icon. We want to end up with four lines in total. The first and third should be 45px long, and the second and fourth should be 62px long. We also want a vertical gap between each of 16px.

We can achieve this with the following code:

1
<line x1="3" y1="3" x2="48" y2="3"></line>
2
<line x1="3" y1="19" x2="65" y2="19"></line>
3
<line x1="3" y1="35" x2="48" y2="35"></line>
4
<line x1="3" y1="51" x2="65" y2="51"></line>
The y values of each line incrementally increase by 16px in order to create the required vertical gap.

Take another look at your browser preview and you should see all four lines. You can also edit the SVG directly in this pen:

Comment Out Your Icons As We Go

With that code in place, your first icon is already made. We’re ready to move onto creating the next icon, and we’re going to want to make it in the same position on the grid, but right now the left align icon is in the way. As such, for now just comment out its code to clear the space. We’re going to come back and uncomment it later when we turn our icons into reusable assets.

You’ll need to do the same thing for each icon as we go, commenting it out after you finish creating it. For that reason it’s probably also a good idea to add a little note above the code for each icon so you know which is which when you come back to them later.

3. Create a “Right Caret” Icon

For this icon, let’s use the next evolution of the <line> element: the <polyline>. We’ll be using it to create a right pointing caret.

The <polyline> element only has one attribute: points. In here you use pairs of numbers to set a series of points. Lines will automatically be drawn between them. The number pairs are simply written one number after the other inside the points attribute. Comma separation is not required, though it can optionally be included. For readability you might also like to put each pair of values on its own line in your code.

We’re going to start our right caret’s polyline at the same spot we started our last icon, that being (3,3) to ensure our stroke and caps don’t get clipped. We want our second point to move over to the right, and down by 25px, so we’ll set it to (30,28). Our third point should be vertically aligned with the first point, and move down by another 25px, so it will be set to (3,53).

We can add these points into our polyline’s points attribute like so:

1
<polyline points="

2
  3 3

3
  30 28

4
  3 53

5
"></polyline>

If you want more concise code, you could also write the above as:

1
<polyline points="3 3, 30 28, 3 53"></polyline>

or

1
<polyline points="3 3 30 28 3 53"></polyline>

Take a look at your browser preview and you should see your right caret icon showing: another icon done, just like that! 

Once again, comment out this icon and give it a little note so you know which one it is before moving onto the next icon.

4. Create a “Browser” Icon

Now we have lines down pat, let’s create some shapes, starting with a rectangle (<rect>). We’re going to use it in conjunction with a couple of <line>s to create a browser icon.

Rectangles and squares can be created with the <rect> element, which has four attributes you’ll need to provide:

  • x the top left corner position on the x axis
  • y the top left corner position on the y axis
  • width width of the shape
  • height height of the shape
You can also use the attributes rx and ry to create rounded corners if you’d like.

We’re going to create a rectangle with its top left corner offset by 3px in both directions, again to avoid clipping the stroke, so we’ll use the attributes x="3" y="3". We want it to be 80px wide by 60px high, so we’ll also use the attributes width="80" height="60".

As such our full rectangle code should be:

1
<rect x="3" y="3" width="80" height="60"></rect>

Save your code and take a look at your browser preview. You should see a neat little rectangle sitting there.

Now all we need to do is add a horizontal line across the top, and a vertical line near the top left, as you see depicted in the image at the start of this section. We’ll use the same line creation process as we did before, and our complete browser icon code should look like this:

1
<rect x="3" y="3" width="80" height="60"></rect>
2
<line x1="3" y1="19" x2="83" y2="19"></line>
3
<line x1="20" y1="3" x2="20" y2="17"></line>

Take a moment to look at the coordinates provided in the two line attributes, and maybe change their values around a little bit so you can see how they’re working in this icon.

5. Create an “Alert” Icon

Now that we have rectangles creation under control, let’s try out using <ellipse>s. We’re going to use two of them, along with a <line>, to create this alert icon:

Like rectangles, the <ellipse> element also requires four attributes, however they are a little different to those of rectangles. Instead of using width and height we set a horizontal and vertical radius. And instead of positioning the top left corner of the shape, we position its center:

  • cx the center position on the x axis. Think “cx for center x”.
  • cy the center position on the y axis. Think “cy for center y”.
  • rx the size of the radius on the x axis, i.e. the shape’s height divided in half. Think “rx for radius x”.
  • ry the size of the radius on the y axis, i.e. the shape’s width divided in half. Think “ry for radius y”.

We want a perfectly round circle that’s 80px wide by 80px high, which means we need its radius to be 40px on both axes. We’ll set this with the attributes rx="40" ry="40".

We also want the circle to sit flush with the darkest lines on our graph. Given that our circle will be 80px wide and high, that would place its center point at 40px. We also need to allow for our 3px offset to avoid clipping however, so that means our circle’s center point should be a 43px on both axis. We’ll set this with the attributes cx="43" cy="43".

Putting all that together, we get this code:

1
<ellipse cx="43" cy="43" rx="40" ry="40"></ellipse>

Check your browser preview and you should now see a circle on your page.

We’re going to add a second circle now, to create the dot at the bottom of the exclamation mark. We’ll create this in just the same way, the only difference being we’re going to use an inline style to set the fill to black:

1
<ellipse style="fill:black;" cx="43" cy="65" rx="5" ry="5"></ellipse>

Finally, we just need to add a line to create the other part of the exclamation mark. Once again we’re using the same techniques as with the other lines we’ve used so far, with the only difference being we’ll use an inline style to thicken this stroke width up from 5px to 8px.

The completed code for our alert icon is as follows:

6. Create a “Play” Icon

Now we have the hang of the relatively fixed shapes of rectangles and ellipses, we’re ready to roll our own shapes using the <polygon> element. We can create any multi-sided shape we want with this, from octagons to stars. However we’ll keep things straight forward for now and create a triangle. We’ll combine it with an <ellipse> to create a play icon:

The <polygon> element is almost identical to the <polyline> element. It too has just one attribute, points, in which you use pairs of values to set each point that makes up the shape. The difference is that while a polyline will remain open, a polygon will automatically close itself.

Let’s start by getting the circle down that our polygon will sit inside of. We’ll use the exact same ellipse we did in our alert icon:

1
<ellipse cx="43" cy="43" rx="40" ry="40"></ellipse>

Now let’s create our polygon. We’re going to place three points, and lines will automatically be generated between these points to create a triangle. The points will be (35,23), (60,43) and (35,63). As such our polygon’s code will be:

1
<polygon points="35 23, 60 43, 35 63" />

And our complete play icon’s code is:

7. Create a “Download” Icon

Now we’ll move onto the most potentially complex, but simultaneously most flexible means of producing SVG shapes, and that is the <path> element. Creating a path is a little like creating a polygon, where you lay out your shape a piece at a time. However with a path you directly create each point and line yourself without automation, and you also have the option to create curves between points instead of straight lines.

A path can be used to create just about anything, but beyond a certain level of complexity you are still better off using a vector design application rather than hand coding. For that reason, we’re going to focus on a small subset of path functionality, and use it to create this download icon:

Technically, you could create the above shape with a polygon, but this arrow will give us a good way to get across how the path element works.

We’ll be using only one of the attributes of <path>, and that is d. The d stands for “data”, and it’s in here you’ll define all the points and lines of your path. Within this attribute, commands to set the points of a path and create lines between them are provided via single letters such as M or L, followed by a set of x and / or y coordinates.

There are several of these commands, but to give you an intro to working with <path> we’ll stick to a few that can be realistically used when hand coding. They are as follows:

  • M Represents moveto. It starts a new path at a given position, defined with x and y values. Imagine this is like hovering your mouse over a point on your canvas, ready to draw. The capital M indicates moving to an absolute set of coordinates. (Lower case m would indicate relative coordinates).
  • L Represents lineto. Draw a line from the current position to a new position. The capital L indicates moving to an absolute set of coordinates. (Lower case l would indicate relative coordinates).
  • Z Represents closepath. It converts the path into a closed shape by drawing a straight line between the current point to the first point created in the path.

You should definitely view these three commands, (and the icon we’ll create with them), as an introductory primer to the <path> element. To really get the most out of it you’ll want to familiarize yourself with all the commands at your disposal.

Code Your Download Icon

To code your download icon path I recommend first adding in the empty path element:

1
<path d="

2


3
"></path>

From here, add in each command one at a time, saving and viewing the progress of the shape so you see how it is created. I also recommend putting each command on its own line for readability.

  1. First, we want to move to (18,3), the point at which we want our arrow to begin. To do this we’ll add the command M 18 3 to our path’s d attribute.
  2. Next we want to use the L command to create a line that draws from our path’s starting point along the x axis for 28px. To do that let’s add our second command: L 46 3. Check your preview and you should see a small horizontal line.
  3. Now let’s draw a line straight down for 37px by adding L 46 40.
  4. Then straight to the right by 15px with L 61 40
  5. Next up we have to begin creating the arrow point. We need to draw a line diagonally down and to the left. We’ll do this with L 32 68.
  6. And then we’ll have a line go diagonally back up and to the left with L 3 40.
  7. Now we’ll finish our arrow head by drawing a little ways to the right again with L 18 40.
  8. To close our shape we don’t need to specify a point to draw a line to. All we need to do is add the Z command, which will automatically close our shape for us.

Your final arrow path code should look like this:

1
<path d="

2
  M 18 3

3
  L 46 3

4
  L 46 40

5
  L 61 40

6
  L 32 68

7
  L 3 40

8
  L 18 40

9
  Z

10
"></path>

For more info on working with <path> check out the references at the bottom of the page.

8. Add <defs> Element

We’re all done coding up our six icons, so now we can get them ready for placement and reuse in our SVG.

To do this we’re going to wrap the code for all six of our, (presently commented out), icons with the tags <defs></defs>:

1
<defs>
2
<!-- All the icons you created so far go in here -->
3
</defs>

This tells the system that all the icons we’ve made are to be hidden by default, until we explicitly use them.

You can now uncomment each of your icons and they won’t be seen on the page.

9. Create Groups With <g>

There are two ways we can make our icons ready for use: by converting them to groups, or into symbols. We’ll turn the first half of the icons into groups, and the second half into symbols so we can illustrate the difference.

To convert one of our icons into a group all we have to do is wrap it with <g></g> tags. To make that group usable we also need to give it a unique ID.

For example:

1
<g id="leftalign">
2
<!-- Left align icon made with lines -->
3
<line x1="3" y1="3" x2="48" y2="3"></line>
4
<line x1="3" y1="19" x2="65" y2="19"></line>
5
<line x1="3" y1="35" x2="48" y2="35"></line>
6
<line x1="3" y1="51" x2="65" y2="51"></line>
7
</g>

Wrap each of your first three icons with <g></g> tags and add unique IDs, like so:

1
<g id="leftalign">
2
<!-- Left align icon made with lines -->
3
<line x1="3" y1="3" x2="48" y2="3"></line>
4
<line x1="3" y1="19" x2="65" y2="19"></line>
5
<line x1="3" y1="35" x2="48" y2="35"></line>
6
<line x1="3" y1="51" x2="65" y2="51"></line>
7
</g>
8
9
<g id="rightcaret">
10
<!-- Right caret icon made with a polyline -->
11
<polyline points="

12
  3 3

13
  30 28

14
  3 53

15
"></polyline>
16
</g>
17
18
<g id="browser">
19
<!-- Browser icon made with rectangle and lines -->
20
<rect x="3" y="3" width="80" height="60"></rect>
21
<line x1="3" y1="19" x2="83" y2="19"></line>
22
<line x1="20" y1="3" x2="20" y2="17"></line>
23
</g>

10. Place Groups With <use>

We now have three icons defined as groups in our <defs> element, so we’re ready to use them in our SVG. To achieve this, all we need to do is add a <use> element, (being sure to add it after and outside the <defs> element), and set an href attribute to target the desired icon’s ID.

For example, to use the left align icon add this code:

1
<use href="#leftalign"></use>

To position the icon in a specific location add x and y attributes:

1
<use href="#leftalign" x="100" y="100"></use>

The code to add all three icons and space them apart would look something like this:

1
<use href="#leftalign" x="100" y="100"></use>
2
3
<use href="#rightcaret" x="300" y="100"></use>
4
5
<use href="#browser" x="500" y="100"></use>

Check your browser and you should see all three of your first icons:

11. Create Symbols With <symbol>

Instead of using groups to define your icons you can also use symbols. Symbols are almost the same as groups, however you gain access to additional settings to control the viewbox and aspect ratio.

This can be very useful if you want to do things like centering the icons we’ve created so far. We’ll turn the remaining three icons into symbols, then adjust them so they’ll vertically fill a 100px high space, and be horizontally centered in that space.

We create our symbols in the same way as our groups, only we’ll be wrapping each of our last three icons’ code in <symbol></symbol> tags. We’ll also need to add a unique ID to each.

However what we’re also going to add is a viewBox attribute. This will let us define what the visible portion of each symbol should be. When the browser has access to this information it can then scale and align symbols correctly.

We’ll need to give our viewBox attribute four values. The first two will define the top left point of our icon, and the third and fourth define its width and height respectively.

Starting with our “alert” icon, its width and height are both 86px so we will set its viewBox to 0 0 86 86 like so:

1
<symbol id="alert" viewBox="0 0 86 86">
2
<!-- Alert icon made with ellipses and a line -->
3
<ellipse cx="43" cy="43" rx="40" ry="40"></ellipse>
4
<ellipse style="fill:black;" cx="43" cy="65" rx="5" ry="5"></ellipse>
5
<line style="stroke-width: 8;" x1="43" y1="19" x2="43" y2="48"></line>
6
</symbol>

The “play” icon is also 86px in width and height, and the “download” icon is 64px wide by 71px high. The corresponding code for our symbols should therefore be:

1
<symbol id="alert" viewBox="0 0 86 86">
2
<!-- Alert icon made with ellipses and a line -->
3
<ellipse cx="43" cy="43" rx="40" ry="40"></ellipse>
4
<ellipse style="fill:black;" cx="43" cy="65" rx="5" ry="5"></ellipse>
5
<line style="stroke-width: 8;" x1="43" y1="19" x2="43" y2="48"></line>
6
</symbol>
7
8
<symbol id="play" viewBox="0 0 86 86">
9
<!-- Play icon made with ellipse and polygon -->
10
<ellipse cx="43" cy="43" rx="40" ry="40"></ellipse>
11
<polygon points="35 23, 60 43, 35 63" />
12
</g>
13
14
<symbol id="download" viewBox="0 0 64 71">
15
<!-- Download icon made with path -->
16
<path d="

17
  M 18 3

18
  L 46 3

19
  L 46 40

20
  L 61 40

21
  L 32 68

22
  L 3 40

23
  L 18 40

24
  Z

25
"></path>
26
</symbol>

12. Place Symbols With <use>

We can now use our symbol icons in the same way as we did our groups. However we’re also going to provide each with width and height attributes set to 100:

1
<use href="#alert" x="100" y="200" width="100" height="100"></use>
2
3
<use href="#play" x="300" y="200" width="100" height="100"></use>
4
5
<use href="#download" x="500" y="200" width="100" height="100"></use>

You’ll see that each one of your symbol based icons neatly fills and aligns in its 100px by 100px space:

Try applying width and height attributes to the <use> elements of one of your group based icons. You’ll notice that nothing changes. This is because the browser relies on viewBox values, (which a group cannot have), in order to know how to scale the icons.

Wrapping Up

That covers the essentials of hand coding SVG! Let’s recap and summarize what we learned:

  • Setup your <svg> element to wrap your whole graphic.
  • Use <line> and <polyline> to create lines.
  • Use <rect>, <ellipse> and <polygon> to create closed shapes.
  • Use <path> to create anything you want.
  • Group shapes with the <g> element.
  • For group like behavior with extra features, use <symbol>
  • Use the <defs> element to define any reusable symbols and groups.
  • Place your defined reusable symbols and groups with the <use> element.

We learned some solid foundations in this tutorial, but there’s a lot more you can do with SVG so don’t stop here, keep digging and discovering more of the awesome things that can be achieved!

In the meantime, hopefully you no longer feel entirely dependent on vector design apps for your SVG creation, and you’re confident to produce some of your own graphics by hand. For more complex graphics, design apps are still the way to go, but there’s a whole lot you can do with the building blocks you have at your disposal, taking advantage of the speed and control hand coding brings.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.