Intro

When it comes to creating an SVG for the web, drawing it is only the beginning. If you don’t have a process down, you still may need to clear the hurdles of optimization, animation, and cross-device testing. To practice these steps, I decided this week to create this SVG emoji to see what I could glean from the experience, and what I could share with other artists, web developers, and technology enthusiasts.

The emoji to which I am referring is below. Give it a tap or a click to see what happens.

In comparison to my earlier face, which I created via coding instead of drawing, I created this one in Inkscape and optimized the code with SVG OMG. So it is a bit more expressive and detailed with eyebrows and a nose.

Objectives

In this tutorial, we’ll look at examine the image was optimized and how the face color, eyebrows, eyes, and mouth were animated. This will involve several steps:

  • optimizing the face in Inkscape and SVG OMG so we get rid of unnecessary code “under the hood.”
  • identifying the various elements in this SVG
  • animating the eyebrows and mouth on tap with a simple CSS transform

Tools:

I found the tools below to be helpful, though you could complete this whole thing with a text editor and a browser. The most essential tool is SVG OMG.

And here we go

Process

Below is the general process I used, followed by a few tips.

  • Create the image in Inkscape
  • Modify the document settings and remove unnnecessary transforms (see below)
  • Upload the image to SVG OMG
  • Admire the memory size reduction
  • Download the optimized file
  • Embed the image by pasting the code into your HTML file, markdown file, or HTML editor
  • Removed the xlmns attribute from the svg object

Inkscape Tips

Below I have a few tips on setting dimensions and eliminating unnecessary “transform” attributes during the Inkscape creation step.

  • Right off the bat, it helps to go to file > document properties and modify the document to fit the image. After a little experimenting, I ultimately made the document 110px by 110px.
  • Inkscape has a “relative move” setting which can make the resulting code more complex. So with all objects selected, go to the </strong>transform</strong> panel. Uncheck relative move and check apply to each object separately. This will help to prevent some unnecessary transforms from showing up in your SVG code.
  • To preview how the art will look in code, go to edit > XML editor and keep that editor open as you work so you can check for unnecessary transforms being applied to your image elements.
  • Every so often and especially towards the end, I find it helpful to click through each object, remove any transforms, and reposition the object if necessary.
  • For layers that already have transformed applied to them, I have found it useful to just create a new layer, cut the objects out of the old layer, and paste them into the new one.
  • Keeping your paths ungrouped will help to make them easier to edit and animate later.

SVG OMG Tips

Here are a few tips about prep, settings, and post-omg modifications.

  • In terms of getting the image ready for the OMG step, I found that converting the units from pt to px in Inkscape was necessary for not cutting off the image in the SVG OMG editor.
  • In SVG OMG itself, I kept the default settings except for unchecking “remove viewbox.” It looks like viewbox still shows up either way but I like to have this setting unchecked just in case.
  • Check “prettify markup” to make the code easy to edit.
  • Uncheck “merge paths” if you want to keep particular elements separate. This can be important if you want to animate, say, a mouth by itself and don’t want it merged with the nose.
  • After downloading the SVG OMG file, I pasted in the markup directly and added a few classes for animation.
A note on illustration: As I mentioned above, I used a Wacom Graphics tablet for drawing the face, but except for the mouth, which has a little nuance to it, the rest could have been done fairly easily without it. In Inkscape, I mainly used the ellipse tool for the face and eyes and the freehand draw tool for the other facial features, though the Bezier tool is worth trying for the eyebrows and nose.

The code up close

A primer on the markup

  • You’ll see the code for just the HTML and SVG markup below. After downloading the file from SVG OMG added a class of face to the SVG, a class of mouth to the mouth, and a class of eyebrow to each eyebrow path, all of which I will use for the animation.
  • I also have an ontouchstart listener on the main SVG element, which is absolutely essential for making the SVG respond to touch on mobile Safari.
  • You’ll see from viewing the source code of this page that we are “inlining” the SVG, or putting the code right into the HTML, rather than using an img element or a background property. This is so we can animate its sub-elements — in this case, the mouth and the two eyebrows.
  • The same svg markup is paired with the CSS further down.
 
  
 
 

Here is the face again so you can see it right after the svg markup.

Animating with CSS

Here is how I animated the face with CSS.

The “active” Pseudo-selector

I used the “active” pseudo selector to the face SVG because the ellipse, eyebrows, eyes, nose, and mouth are all children of that element. You could use the “hover” pseudo-selector, but it does not work as well on mobile devices — it often just stays in its hover state after you tap it, which would leave the face in a state of perpetual shock.

Transition
  • For both active and non-active states of most elements, I added a transition with a 0.3s and an ease of “ease-out,” which gives it a quicker start and a slower end.
  • You’ll see in the CSS that I used webkit variants of transforms and transitions so that the styles work well Chrome, Safari, and other browsers that use the webkit browser engine.

Beyond these general approaches, here is how I animated specific parts of the SVG.

Face color change

To achieve the “face getting pale” effect I change the fill color of the ellipse, which is the outline of the face. Note that the fill color of #ffeeaa is in the svg itself, so I only specify the color of the face in the :active svg.

	
.face ellipse {
  transition: fill 0.3s ease;
  -webkit-transition: fill 0.3s ease;
}
.face:active ellipse {
  fill: #FFFFDD;
  transition: fill 0.3s ease;
  -webkit-transition: fill 0.3s ease;
}
    
Eyebrows

To move the eyebrows up, I used a “transform” of translateY and just bring it up by 3 pixels. Even though SVG’s are not made of pixels they are still handy to use as measurements in the CSS!

	
.face:active .eyebrow {
  transform: translateY(-3px);
  -webkit-transform: translateY(-3px);
}
    
Eyes

The eyes were an interesting case, in that it was challenging to get a scale transform to work smoothly in Firefox. However I tried it, it came out choppy. I ended up animating the stroke-width and targeted this property specifically with my transition, which gave me solid results across Chrome, Safari, and Firefox browsers.

	
.face .eye {
  stroke-width: 0px;
  stroke: #000000;
  transition: stroke-width 0.3s ease-out;
}
.face:active .eye {
   stroke-width: 0.5px;
   transition: stroke-width 0.3s ease-out;
}
	
Mouth
  • To enlarge the mouth, I use a “transform” of both scale and translate.
  • Notice also that I am using transform-origin to center the mouth, but it’s not enough — I also need translate to keep it centered properly. I am still looking into the reason for this.
  • I had to use an integer for the radius of the mouth in order to achieve a smooth animation.
	
.face .mouth {
  transform: translateY(0px) scale(1);
  -webkit-transform:translateY(0px) scale(1);

  transform-origin: center center;
  -webkit-transform-origin: center center;
}
.face:active .mouth {
  transform:  translate(1px,-22px) scale(3);
  -webkit-transform: translate(1px,-22px) scale(3);
}
	

Putting it all together

Here is the complete markup and CSS.

 
  
 
 
 /* face */
.face ellipse {
  transition: fill 0.3s ease;
  -webkit-transition: fill 0.3s ease;
}
.face:active ellipse {
  fill: #FFFFDD;
  transition: fill 0.3s ease;
  -webkit-transition: fill 0.3s ease;
}
/* eyebrow and mouth defaults */
.eyebrow, .mouth {
  transition: 0.3s ease-out;
  -webkit-transition: 0.3s ease-out;
}
.face:active .mouth, 
.face:active .eyebrow {
  transition: 0.3s ease-out;
  -webkit-transition: 0.3s ease-out;

}
/* eyebrows */
.face:active .eyebrow {
  transform: translateY(-3px);
  -webkit-transform: translateY(-3px);
}

/* mouth */
.face .mouth {
  transform: translateY(0px) scale(1);
  -webkit-transform:translateY(0px) scale(1);
  transform-origin: center center;
  -webkit-transform-origin: center center;
}
/* enlarge mouth and move it to keep it centered */
.face:active .mouth {
  transform:  translate(1px,-22px) scale(3);
  -webkit-transform: translate(1px,-22px) scale(3);

}
/* eyes */
.face .eye {
  stroke-width: 0px;
  stroke: #000000;
  transition: stroke-width 0.3s ease-out;
}
.face:active .eye {
   stroke-width: 0.5px;
   transition: stroke-width 0.3s ease-out;
}

 

Takeaways

  • Image authoring tools like Inkscape usually export SVG’s with unnecessary code.
  • Use a tool like SVG OMG to optimize your SVG markup.
  • Use “ontouchstart” attribute to make your SVG elements respond to touch on mobile Safari.
  • You can animate the elements of inline SVG’s using CSS transforms.

I was originally thinking of writing about 12 faces in one post, but one emoji at a time is clearly the way to go since so much learning happens with each one.

It has occurred to me that it would be cool to reduce the size of these and show how they might be used inline with some text. If you’d like to see how I’d do that, let me know.

I hope you’ve found this helpful. In upcoming posts, we’ll take a look at a few other emojis, how they look in code, and how they can be animated.