Skip to content

Latest commit

 

History

History
364 lines (318 loc) · 11.3 KB

svg-smiley-face.md

File metadata and controls

364 lines (318 loc) · 11.3 KB
layout title desc hide_show_for_marks markbot_submit extra_tutorials goal fork steps
lesson
SVG smiley face
Hand write SVG code to create an interactive smiley face.
true
true
title url
Advanced SVG
advanced-svg
title url
Advanced SVG slide deck
/courses/web-dev-3/advanced-svg/
title url highlight
SVG cheat sheet
svg-cheat-sheet
true
title url
CSS animations & effects cheat sheet
css-animations-effects-cheat-sheet
before no_image video video_poster notes
We’re going to look at hand writing some SVG & CSS to create an interactive smiley face. When hovering over the face the eyebrows will tilt from happy to angry positions.
true
goal.jpg
label text
Type it, type it real good
Remember the purpose of this lesson is to type the code out yourself—build up that muscle memory in your fingers!
title before folders after notes
Set up project
Before we get started, create some files and get ready.
label type
smiley-face
folder
label indent
index.html
1
label type indent
css
folder
1
label indent
main.css
2
1. Make an `index.html` & add the boilerplate code. 2. Make a `main.css` in your `css` folder—it can remain empty.
label text
Naming conventions
Don’t forget to follow the [naming conventions](/topics/naming-paths-cheat-sheet/#naming-conventions).
label text
HTML snippets
Create the boilerplate with `html5`, `viewport`, `css`
title before code_lang code_file code lines
SVG wrapper
Inside our HTML we’ll start by writing the code for the SVG—specifically defining the dimensions and the artboard.
html
index.html
⋮ </head> <body> <svg class="smiley" width="256" height="256" viewBox="0 0 256 256"> </svg> </body> </html> ⋮
num fade
2-3
true
num text
5
We can add `class` attributes to the SVG elements. The `width` & `height` define the dimensions of the image. --- The `viewBox` defines the artboard in the image, a cropping zone. It’s almost always the same as the width & height. - `0 0` — the top left corner’s x & y coordinates. - `256 256` — the width and height of the art board.
num fade
9-10
true
title before code_lang code_file code lines after
Draw the face circle
Using SVG’s `<circle>` tag we can create the face.
html
index.html
⋮ <svg class="smiley" width="256" height="256" viewBox="0 0 256 256"> <circle class="face" cx="128" cy="128" r="120" /> </svg> ⋮
num fade
2
true
num text
3
- `cx` — the center x coordinate, measured from the left of the image - `cy` — the center y coordinate, measured from the the top of the image - `r` — the radius of the circle, measured from the `cx` & `cy` Notice the closing slash at the end of the `<circle … />` tag: because this is XML self-closing tags **must** include their own slash.
num fade
4
true
You should see a black circle when you refresh in the browser. *Here’s an explanation of the different attributes on the `<circle>` tag:* ![](face.png)
title before code_lang code_file code lines after
Make the face yellow
SVGs use CSS for much of their visual style—the only difference is the properties that are used to apply visual design.
css
css/main.css
.face { fill: gold; }
num text
1
We select things the same as with HTML, using classes or tags.
num text
2
The `fill` property is used to colour SVG shapes.
![](face-yellow.png)
title before code_lang code_file code lines after
Add the eyes
Using two more `<circle>` tags we can add the eyes onto our smiley face.
html
index.html
⋮ <svg class="smiley" width="256" height="256" viewBox="0 0 256 256"> <circle class="face" cx="128" cy="128" r="120" /> <circle class="left-eye" cx="100" cy="104" r="12" /> <circle class="right-eye" cx="156" cy="104" r="12" /> </svg> ⋮
num fade
2-3
true
num text
4-5
Two new circles. We don’t need to add `fill` because they’ll automatically be black.
num fade
6
true
![](eyes.png)
title before code_lang code_file code lines after
Add the mouth
Using the SVG `<path>` tag we can create really complex paths and shapes. We can use it now to make the smile.
html
index.html
⋮ <svg class="smiley" width="256" height="256" viewBox="0 0 256 256"> <circle class="face" cx="128" cy="128" r="120" /> <circle class="left-eye" cx="100" cy="104" r="12" /> <circle class="right-eye" cx="156" cy="104" r="12" /> <path class="mouth" d="M100,160 Q128,190 156,160" /> </svg> ⋮
num fade
2-5
true
num text
6
All the fanciness for the `<path>` is controlled by the `d=""` attribute—it gives coordinates for anchor points and for control handles. - `M100,160` — the starting anchor point for the path. - `Q128,190` — means we want to use a quadratic bézier curve, giving us only one control handle for the curve. The coordinates are the handle’s location. - `156,160` — the coordinate for the last anchor point.
num fade
7
true
In the `d=""` attribute there’s a lot of complexity going on, here’s a break down of what each thing is doing. ![](mouth.png) **You won’t be able to see the mouth in your browser yet.**
title before code_lang code_file code lines after
Style the mouth
We can’t see the mouth in our SVG face yet because the path exists but it doesn’t have a defined, visible stroke. We do that with CSS.
css
css/main.css
⋮ .face { fill: gold; } .mouth { fill: none; stroke: #000; stroke-width: 6px; stroke-linecap: round; }
num fade
2-4
true
num text
8
The colour of the stroke on the shape.
num text
9
The thickness of the shape’s stroke.
num text
10
Makes the ends of the stroke into rounded corners instead of sharp edges.
*Now the mouth should be visible in the browser.*
title before code_lang code_file code lines after
Add the eyebrows
Let’s use the `<rect>` tag to create a set of eyebrows.
html
index.html
⋮ <svg class="smiley" width="256" height="256" viewBox="0 0 256 256"> <circle class="face" cx="128" cy="128" r="120" /> <circle class="left-eye" cx="100" cy="104" r="12" /> <circle class="right-eye" cx="156" cy="104" r="12" /> <path class="mouth" d="M100,160 Q128,190 156,160" /> <rect class="left-eyebrow" x="97" y="66" width="6" height="32" rx="4" ry="4" /> <rect class="right-eyebrow" x="153" y="66" width="6" height="32" rx="4" ry="4" /> </svg> ⋮
num fade
2-6
true
num text
7-8
There are a bunch of attributes here to create the rectangle: - `x` — the top left x coordinate - `y` — the top left y coordinate - `width` — how wide the rectangle is - `height` — how tall the rectangle is - `rx` — the horizontal border-radius size - `ry` — the vertical border-radius size
num fade
9
true
This is what we should be looking at in our browser right now: ![](eyebrows.png)
title before code_lang code_file code lines after
Rotate the eyebrows
Using the CSS `transform: rotate()` property we can adjust the eyebrows to look happy.
css
css/main.css
⋮ stroke-width: 6px; stroke-linecap: round; } .left-eyebrow { transform: rotate(80deg); } .right-eyebrow { transform: rotate(100deg); }
num fade
2-4
true
**If we look in the browser right now we won’t see the eyebrows any more.** It’s because `transform-origin` is set to the top-left of the SVG by default. Here’s a little visualization of what’s happening right now: ![](busted-eyebrows.png)
title before code_lang code_file code lines after
Fix the eyebrow anchor points
We want to get the `transform-origin` anchor point in the center of the rectangle, but `center center` doesn’t work on SVG. So we need to use pixel coordinates instead.
css
css/main.css
⋮ .left-eyebrow { transform: rotate(80deg); transform-origin: 100px 82px; } .right-eyebrow { transform: rotate(100deg); transform-origin: 156px 82px; }
num fade
3
true
num text
4
- The horizontal point, `100px`, is the exact center of the rectangle measured from the left edge. - The vertical point, `82px`, is the exact center of the rectangle measure from the top edge.
num fade
8
true
With these `transform-origin` properties we can now see the eyebrows exactly where we want them to be. Here’s a little visualization of where those numbers came from: ![](eyebrow-transform-origin.png)
title before code_lang code_file code lines after
Interactivity with transitions
Let’s add a little interactivity with transitions. We’re going to make the eyebrows rotate into an angry state when you hover over the face.
css
css/main.css
⋮ .left-eyebrow { transform: rotate(80deg); transform-origin: 100px 82px; transition: all .5s linear; } .right-eyebrow { transform: rotate(100deg); transform-origin: 156px 82px; transition: all .5s linear; } .smiley:hover .left-eyebrow { transform: rotate(100deg); } .smiley:hover .right-eyebrow { transform: rotate(80deg); }
num fade
3-4
true
num text
5
Add a `transition` to the default state for the eyebrows so they’ll be animated when hovered.
num fade
9-10
true
num text
14
Read this selector from right-to-left: “choose the `.left-eyebrow` when the user `:hover`s the `.smiley`. I’ve specifically done this so we don’t have to hover directly on the eyebrow for the animation to trigger, we can hover anywhere on the smiley face.
*Try it out!*