{"id":933,"date":"2025-06-04T08:00:00","date_gmt":"2025-06-04T08:00:00","guid":{"rendered":"http:\/\/www.computercoursesonline.com\/?p=933"},"modified":"2025-06-05T21:14:53","modified_gmt":"2025-06-05T21:14:53","slug":"smashing-animations-part-4-optimising-svgs","status":"publish","type":"post","link":"http:\/\/www.computercoursesonline.com\/index.php\/2025\/06\/04\/smashing-animations-part-4-optimising-svgs\/","title":{"rendered":"Smashing Animations Part 4: Optimising SVGs"},"content":{"rendered":"

Smashing Animations Part 4: Optimising SVGs<\/title><\/p>\n<article>\n<header>\n<h1>Smashing Animations Part 4: Optimising SVGs<\/h1>\n<address>Andy Clarke<\/address>\n<p> 2025-06-04T08:00:00+00:00<br \/>\n 2025-06-05T21:02:28+00:00<br \/>\n <\/header>\n<p>SVG animations take me back to the Hanna-Barbera cartoons I watched as a kid. Shows like <em>Wacky Races<\/em>, <em>The Perils of Penelope Pitstop<\/em>, and, of course, <a href=\"https:\/\/en.wikipedia.org\/wiki\/Yogi_Bear\"><em>Yogi Bear<\/em><\/a>. They inspired me to lovingly recreate some classic <a href=\"https:\/\/stuffandnonsense.co.uk\/toon-titles\">Toon Titles<\/a> using CSS, SVG, and SMIL animations.<\/p>\n<p>But getting animations to load quickly and work smoothly needs more than nostalgia. It takes clean design, lean code, and a process that makes complex SVGs easier to animate. Here\u2019s how I do it.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/stuffandnonsense.co.uk\/toon-titles\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"An example of Toon Titles from the website\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/1-toon-titles.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n There\u2019s now a website where you can see all my <a href=\"https:\/\/stuffandnonsense.co.uk\/toon-titles\">Toon Titles<\/a>. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/1-toon-titles.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<div class=\"refs\">\n<ul>\n<li><a href=\"https:\/\/www.smashingmagazine.com\/2025\/05\/smashing-animations-part-1-classic-cartoons-inspire-css\/\">Smashing Animations Part 1: How Classic Cartoons Inspire Modern CSS<\/a><\/li>\n<li><a href=\"https:\/\/www.smashingmagazine.com\/2025\/05\/smashing-animations-part-2-css-masking-add-extra-dimension\/\">Smashing Animations Part 2: How CSS Masking Can Add An Extra Dimension<\/a><\/li>\n<li><a href=\"https:\/\/www.smashingmagazine.com\/2025\/05\/smashing-animations-part-3-smil-not-dead\/\">Smashing Animations Part 3: SMIL\u2019s Not Dead Baby, SMIL\u2019s Not Dead<\/a><\/li>\n<\/ul>\n<\/div>\n<p>Whether for personal projects or commercial work, preparing SVGs well ensures they\u2019re accessible. Optimising them ensures they load quickly, especially on mobile, and thinking carefully about how they\u2019re structured makes maintaining them easier. I\u2019ve developed a <strong>process that balances visuals with accessibility and performance<\/strong> and makes complex SVGs easier to work with.<\/p>\n<p>So, to explain my process, I\u2019ve chosen an episode of <em>The Yogi Bear Show<\/em> called \u201cBewitched Bear,\u201d first broadcast in January 1960. In this story, Yogi steals a witch\u2019s broom to help him grab \u201cpic-a-nic\u201d baskets.<\/p>\n<p>\u201cHey, hey, hey!\u201d<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/2-yogi-bear-bewitched-bear.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"540\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"An illustration from the \u201cBewitched Bear\u201d episode of The Yogi Bear Show where bear is on a witch\u2019s broom\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/2-yogi-bear-bewitched-bear.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n The Yogi Bear Show \u00a9 Warner Bros. Entertainment Inc. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/2-yogi-bear-bewitched-bear.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<div data-audience=\"non-subscriber\" data-remove=\"true\" class=\"feature-panel-container\">\n<aside class=\"feature-panel\">\n<div class=\"feature-panel-left-col\">\n<div class=\"feature-panel-description\">\n<p>Meet <strong><a data-instant href=\"https:\/\/www.smashingconf.com\/online-workshops\/\">Smashing Workshops<\/a><\/strong> on <strong>front-end, design & UX<\/strong>, with practical takeaways, live sessions, <strong>video recordings<\/strong> and a friendly Q&A. With Brad Frost, St\u00e9ph Walter and <a href=\"https:\/\/smashingconf.com\/online-workshops\/workshops\">so many others<\/a>.<\/p>\n<p><a data-instant href=\"smashing-workshops\" class=\"btn btn--green btn--large\">Jump to the workshops \u21ac<\/a><\/div>\n<\/div>\n<div class=\"feature-panel-right-col\"><a data-instant href=\"smashing-workshops\" class=\"feature-panel-image-link\"><\/p>\n<div class=\"feature-panel-image\">\n<img loading=\"lazy\" class=\"feature-panel-image-img lazyload\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Feature Panel\" width=\"257\" height=\"355\" data-src=\"\/images\/smashing-cat\/cat-scubadiving-panel.svg\"><\/p>\n<\/div>\n<p><\/a>\n<\/div>\n<\/aside>\n<\/div>\n<h2 id=\"start-clean-and-design-with-optimisation-in-mind\">Start Clean And Design With Optimisation In Mind<\/h2>\n<p>Keeping things simple is key to making SVGs that are optimised and ready to animate. Tools like Adobe Illustrator convert bitmap images to vectors, but the output often contains too many extraneous groups, layers, and masks. Instead, I start cleaning in Sketch, work from a reference image, and use the Pen tool to create paths.<\/p>\n<blockquote><p><strong>Tip<\/strong>: <a href=\"https:\/\/affinity.serif.com\/en-gb\/designer\/\">Affinity Designer<\/a> (UK) and <a href=\"https:\/\/www.sketch.com\">Sketch<\/a> (Netherlands) are alternatives to Adobe Illustrator and Figma. Both are independent and based in Europe. Sketch has been my default design app since Adobe killed Fireworks.<\/p><\/blockquote>\n<h2 id=\"beginning-with-outlines\">Beginning With Outlines<\/h2>\n<p>For these Toon Titles illustrations, I first use the Pen tool to draw black outlines with as few anchor points as possible. The more points a shape has, the bigger a file becomes, so simplifying paths and reducing the number of points makes an SVG much smaller, often with no discernible visual difference.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/3-outlines-anchor-points.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Two outlines with different anchor points\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/3-outlines-anchor-points.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n <strong>Left<\/strong>: 160 anchor points. <strong>Right<\/strong>: 80 points. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/3-outlines-anchor-points.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>Bearing in mind that parts of this Yogi illustration will ultimately be animated, I keep outlines for this Bewitched Bear\u2019s body, head, collar, and tie separate so that I can move them independently. The head might nod, the tie could flap, and, like in those classic cartoons, Yogi\u2019s collar will hide the joins between them.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/4-separate-outlines.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Separate outlines for body, head, collar and tie, and broom.\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/4-separate-outlines.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Separate outlines for body, head, collar and tie, and broom. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/4-separate-outlines.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<h2 id=\"drawing-simple-background-shapes\">Drawing Simple Background Shapes<\/h2>\n<p>With the outlines in place, I use the Pen tool again to draw new shapes, which fill the areas with colour. These colours sit behind the outlines, so they don\u2019t need to match them exactly. The fewer anchor points, the smaller the file size.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/5-simple-background-shapes.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Original vector artwork and a simplified version with Adobe Illustrator\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/5-simple-background-shapes.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n <strong>Left<\/strong>: Original vector artwork, 8 Kb. <strong>Right<\/strong>: Simplified using Adobe Illustrator, 2 Kb. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/5-simple-background-shapes.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>Sadly, neither Affinity Designer nor Sketch has tools that can simplify paths, but if you have it, using Adobe Illustrator can shave a few extra kilobytes off these background shapes.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/6-adobe-illustrator-simplify-paths.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"An illustration how to simplify paths with Adobe Illustrator\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/6-adobe-illustrator-simplify-paths.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Adobe Illustrator: Object \u2192 Path \u2192 Simplify. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/6-adobe-illustrator-simplify-paths.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<h2 id=\"optimising-the-code\">Optimising The Code<\/h2>\n<p>It\u2019s not just metadata that makes SVG bulkier. The way you export from your design app also affects file size.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/7-vector-artwork-ready-optimisation.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Vector artwork ready for optimisation.\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/7-vector-artwork-ready-optimisation.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Vector artwork ready for optimisation. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/7-vector-artwork-ready-optimisation.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>Exporting just those simple background shapes from Adobe Illustrator includes unnecessary groups, masks, and bloated path data by default. Sketch\u2019s code is barely any better, and there\u2019s plenty of room for improvement, even in its SVGO Compressor code. I rely on Jake Archibald\u2019s <a href=\"https:\/\/jakearchibald.github.io\/svgomg\/\">SVGOMG<\/a>, which uses SVGO v3 and consistently delivers the best optimised SVGs.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/8-jake-archibald-svgomg-online-optimisation-tool.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"439\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Jake Archibald\u2019s SVGOMG online optimisation tool.\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/8-jake-archibald-svgomg-online-optimisation-tool.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Jake Archibald\u2019s SVGOMG online optimisation tool. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/8-jake-archibald-svgomg-online-optimisation-tool.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<div class=\"partners__lead-place\"><\/div>\n<h2 id=\"layering-svg-elements\">Layering SVG Elements<\/h2>\n<p>My process for preparing SVGs for animation goes well beyond drawing vectors and optimising paths — it also includes how I <strong>structure the code<\/strong> itself. When every visual element is crammed into a single SVG file, even optimised code can be a nightmare to navigate. Locating a specific path or group often feels like searching for a needle in a haystack.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/9-yogi-bear-title-card-toon-titles-recreation.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Toon Titles recreation of the Yogi Bear title card\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/9-yogi-bear-title-card-toon-titles-recreation.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Yogi Bear title card design by Lawrence Goble (1958). Toon Titles recreation. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/9-yogi-bear-title-card-toon-titles-recreation.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>That\u2019s why I develop my SVGs in layers, exporting and optimising one set of elements at a time — always in the order they\u2019ll appear in the final file. This lets me build the master SVG gradually by pasting it in each cleaned-up section. For example, I start with backgrounds like this gradient and title graphic.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/10-gradient-background-title-graphic.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Gradient background and title graphic.\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/10-gradient-background-title-graphic.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Gradient background and title graphic. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/10-gradient-background-title-graphic.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>Instead of facing a wall of SVG code, I can now easily identify the background gradient\u2019s path and its associated <code>linearGradient<\/code>, and see the group containing the title graphic. I take this opportunity to add a comment to the code, which will make editing and adding animations to it easier in the future:<\/p>\n<pre><code class=\"language-svg\"><svg ...>\n <defs>\n <!-- ... -->\n <\/defs>\n <path fill=\"url(#grad)\" d=\"\u2026\"\/>\n <!-- TITLE GRAPHIC -->\n <g>\n <path \u2026 \/>\n <!-- ... --> \n <\/g>\n<\/svg>\n<\/code><\/pre>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/11-trail-gaussian-blur.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Trail with Gaussian Blur.\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/11-trail-gaussian-blur.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Trail with Gaussian Blur. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/11-trail-gaussian-blur.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>Next, I add the blurred trail from Yogi\u2019s airborne broom. This includes defining a Gaussian Blur filter and placing its path between the background and title layers:<\/p>\n<pre><code class=\"language-svg\"><svg ...>\n <defs>\n <linearGradient id=\"grad\" \u2026>\u2026<\/linearGradient>\n <filter id=\"trail\" \u2026>\u2026<\/filter>\n <\/defs>\n <!-- GRADIENT -->\n <!-- TRAIL -->\n <path filter=\"url(#trail)\" \u2026\/>\n <!-- TITLE GRAPHIC -->\n<\/svg>\n<\/code><\/pre>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/12-yogi-bear-magical-stars.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Yogi Bear\u2019s magical stars.\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/12-yogi-bear-magical-stars.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Yogi Bear\u2019s magical stars. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/12-yogi-bear-magical-stars.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>Then come the magical stars, added in the same sequential fashion:<\/p>\n<pre><code class=\"language-svg\"><svg ...>\n <!-- GRADIENT -->\n <!-- TRAIL -->\n <!-- STARS -->\n <!-- TITLE GRAPHIC -->\n<\/svg>\n<\/code><\/pre>\n<p>To keep everything organised and animation-ready, I create an empty group that will hold all the parts of Yogi:<\/p>\n<pre><code class=\"language-svg\"><g id=\"yogi\">...<\/g>\n<\/code><\/pre>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/13-yogi-bear-component-parts.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Added Yogi Bear\u2019s component parts\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/13-yogi-bear-component-parts.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Sequentially adding Yogi Bear\u2019s component parts. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/13-yogi-bear-component-parts.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>Then I build Yogi from the ground up — starting with background props, like his broom:<\/p>\n<pre><code class=\"language-svg\"><g id=\"broom\">...<\/g>\n<\/code><\/pre>\n<p>Followed by grouped elements for his body, head, collar, and tie:<\/p>\n<pre><code class=\"language-svg\"><g id=\"yogi\">\n <g id=\"broom\">\u2026<\/g>\n <g id=\"body\">\u2026<\/g>\n <g id=\"head\">\u2026<\/g>\n <g id=\"collar\">\u2026<\/g>\n <g id=\"tie\">\u2026<\/g>\n<\/g>\n<\/code><\/pre>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/14-yogi-bear-title-card-toon-titles-recreation.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Toon Titles recreation of the Yogi Bear title card\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/14-yogi-bear-title-card-toon-titles-recreation.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Yogi Bear title card design by Lawrence Goble (1958). Toon Titles recreation. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/14-yogi-bear-title-card-toon-titles-recreation.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>Since I export each layer from the same-sized artboard, I don\u2019t need to worry about alignment or positioning issues later on — they\u2019ll all slot into place automatically. I keep my code <strong>clean<\/strong>, <strong>readable<\/strong>, and <strong>ordered logically<\/strong> by layering elements this way. It also makes animating smoother, as each component is easier to identify.<\/p>\n<h2 id=\"reusing-elements-with-use\">Reusing Elements With <code><use><\/code><\/h2>\n<p>When duplicate shapes get reused repeatedly, SVG files can get bulky fast. My recreation of the \u201cBewitched Bear\u201d title card contains 80 stars in three sizes. Combining all those shapes into one optimised path would bring the file size down to 3KB. But I want to animate individual stars, which would almost double that to 5KB:<\/p>\n<pre><code class=\"language-svg\"><g id=\"stars\">\n <path class=\"star-small\" fill=\"#eae3da\" d=\"...\"\/>\n <path class=\"star-medium\" fill=\"#eae3da\" d=\"...\"\/>\n <path class=\"star-large\" fill=\"#eae3da\" d=\"...\"\/>\n <!-- ... -->\n<\/g>\n<\/code><\/pre>\n<p>Moving the stars\u2019 <code>fill<\/code> attribute values to their parent group reduces the overall weight a little:<\/p>\n<pre><code class=\"language-svg\"><g id=\"stars\" fill=\"#eae3da\">\n <path class=\"star-small\" d=\"\u2026\"\/>\n <path class=\"star-medium\" d=\"\u2026\"\/>\n <path class=\"star-large\" d=\"\u2026\"\/>\n <!-- ... -->\n<\/g>\n<\/code><\/pre>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/15-yogi-bear-sparkling-stars.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Yogi Bear\u2019s sparkling stars.\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/15-yogi-bear-sparkling-stars.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Yogi Bear\u2019s sparkling stars. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/15-yogi-bear-sparkling-stars.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>But a more efficient and manageable option is to define each star size as a reusable template:<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-svg\"><defs>\n <path id=\"star-large\" fill=\"#eae3da\" fill-rule=\"evenodd\" d=\"\u2026\"\/>\n <path id=\"star-medium\" fill=\"#eae3da\" fill-rule=\"evenodd\" d=\"\u2026\"\/>\n <path id=\"star-small\" fill=\"#eae3da\" fill-rule=\"evenodd\" d=\"\u2026\"\/>\n<\/defs>\n<\/code><\/pre>\n<\/div>\n<p>With this setup, changing a star\u2019s design only means updating its template once, and every instance updates automatically. Then, I reference each one using <code><use><\/code> and position them with <code>x<\/code> and <code>y<\/code> attributes:<\/p>\n<pre><code class=\"language-svg\"><g id=\"stars\">\n <!-- Large stars -->\n <use href=\"#star-large\" x=\"1575\" y=\"495\"\/>\n <!-- ... -->\n <!-- Medium stars -->\n <use href=\"#star-medium\" x=\"1453\" y=\"696\"\/>\n <!-- ... -->\n <!-- Small stars -->\n <use href=\"#star-small\" x=\"1287\" y=\"741\"\/>\n <!-- ... -->\n<\/g>\n<\/code><\/pre>\n<p>This approach makes the SVG easier to manage, lighter to load, and faster to iterate on, especially when working with dozens of repeating elements. Best of all, it keeps the markup clean <strong>without compromising on flexibility or performance<\/strong>.<\/p>\n<div class=\"partners__lead-place\"><\/div>\n<h2 id=\"adding-animations\">Adding Animations<\/h2>\n<p>The stars trailing behind Yogi\u2019s stolen broom bring so much personality to the animation. I wanted them to sparkle in a seemingly random pattern against the dark blue background, so I started by defining a keyframe animation that cycles through different <code>opacity<\/code> levels:<\/p>\n<pre><code class=\"language-css\">@keyframes sparkle {\n 0%, 100% { opacity: .1; }\n 50% { opacity: 1; }\n}\n<\/code><\/pre>\n<p>Next, I applied this looping animation to every <code>use<\/code> element inside my stars group:<\/p>\n<pre><code class=\"language-css\">#stars use {\n animation: sparkle 10s ease-in-out infinite;\n}\n<\/code><\/pre>\n<p>The secret to creating a convincing twinkle lies in <strong>variation<\/strong>. I staggered animation delays and durations across the stars using <code>nth-child<\/code> selectors, starting with the quickest and most frequent sparkle effects:<\/p>\n<pre><code class=\"language-css\">\/* Fast, frequent *\/\n#stars use:nth-child(n + 1):nth-child(-n + 10) {\n animation-delay: .1s;\n animation-duration: 2s;\n}\n<\/code><\/pre>\n<p>From there, I layered in additional timings to mix things up. Some stars sparkle slowly and dramatically, others more randomly, with a variety of rhythms and pauses:<\/p>\n<pre><code class=\"language-css\">\/* Medium *\/\n#stars use:nth-child(n + 11):nth-child(-n + 20) { ... }\n\n\/* Slow, dramatic *\/\n#stars use:nth-child(n + 21):nth-child(-n + 30) { ... }\n\n\/* Random *\/\n#stars use:nth-child(3n + 2) { ... }\n\n\/* Alternating *\/\n#stars use:nth-child(4n + 1) { ... }\n\n\/* Scattered *\/\n#stars use:nth-child(n + 31) { ... }\n<\/code><\/pre>\n<p>By thoughtfully structuring the SVG and reusing elements, I can build complex-looking animations without bloated code, making even a simple effect like changing <code>opacity<\/code> sparkle.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/16-subtle-movements-yogi-bear.png\"><\/p>\n<p> <img loading=\"lazy\" width=\"800\" height=\"450\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Yogi Bear\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/16-subtle-movements-yogi-bear.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Subtle movements bring Yogi Bear to life. (<a href=\"https:\/\/files.smashing.media\/articles\/smashing-animations-part-4-optimising-svgs\/16-subtle-movements-yogi-bear.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>Then, for added realism, I make Yogi\u2019s head wobble:<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-css\">@keyframes headWobble {\n 0% { transform: rotate(-0.8deg) translateY(-0.5px); }\n 100% { transform: rotate(0.9deg) translateY(0.3px); }\n}\n\n#head {\n animation: headWobble 0.8s cubic-bezier(0.5, 0.15, 0.5, 0.85) infinite alternate;\n}\n<\/code><\/pre>\n<\/div>\n<p>His tie waves:<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-css\">@keyframes tieWave {\n 0%, 100% { transform: rotateZ(-4deg) rotateY(15deg) scaleX(0.96); }\n 33% { transform: rotateZ(5deg) rotateY(-10deg) scaleX(1.05); }\n 66% { transform: rotateZ(-2deg) rotateY(5deg) scaleX(0.98); }\n}\n\n#tie {\n transform-style: preserve-3d;\n animation: tieWave 10s cubic-bezier(0.68, -0.55, 0.27, 1.55) infinite;\n}\n<\/code><\/pre>\n<\/div>\n<p>His broom swings:<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-css\">@keyframes broomSwing {\n 0%, 20% { transform: rotate(-5deg); }\n 30% { transform: rotate(-4deg); }\n 50%, 70% { transform: rotate(5deg); }\n 80% { transform: rotate(4deg); }\n 100% { transform: rotate(-5deg); }\n}\n\n#broom {\n animation: broomSwing 4s cubic-bezier(0.5, 0.05, 0.5, 0.95) infinite;\n}\n<\/code><\/pre>\n<\/div>\n<p>And, finally, Yogi himself gently rotates as he flies on his magical broom:<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-css\">@keyframes yogiWobble {\n 0% { transform: rotate(-2.8deg) translateY(-0.8px) scale(0.998); }\n 30% { transform: rotate(1.5deg) translateY(0.3px); }\n 100% { transform: rotate(3.2deg) translateY(1.2px) scale(1.002); }\n}\n\n#yogi {\n animation: yogiWobble 3.5s cubic-bezier(.37, .14, .3, .86) infinite alternate;\n}\n<\/code><\/pre>\n<\/div>\n<p>All these subtle movements bring Yogi to life. By developing structured SVGs, I can create animations that feel full of character without writing a single line of JavaScript.<\/p>\n<p>Try this yourself:<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"bNdwJBN\" data-user=\"smashingmag\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Bewitched Bear CSS\/SVG animation [forked]](https:\/\/codepen.io\/smashingmag\/pen\/bNdwJBN) by <a href=\"https:\/\/codepen.io\/malarkey\">Andy Clarke<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/bNdwJBN\">Bewitched Bear CSS\/SVG animation [forked]<\/a> by <a href=\"https:\/\/codepen.io\/malarkey\">Andy Clarke<\/a>.<\/figcaption><\/figure>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>Whether you\u2019re recreating a classic title card or animating icons for an interface, the principles are the same:<\/p>\n<ol>\n<li>Start clean,<\/li>\n<li>Optimise early, and<\/li>\n<li>Structure everything with animation in mind.<\/li>\n<\/ol>\n<p>SVGs offer incredible creative freedom, but only if kept <strong>lean<\/strong> and <strong>manageable<\/strong>. When you plan your process like a production cell — layer by layer, element by element — you\u2019ll spend less time untangling code and more time bringing your work to life.<\/p>\n<div class=\"signature\">\n <img src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Smashing Editorial\" width=\"35\" height=\"46\" loading=\"lazy\" class=\"lazyload\" data-src=\"https:\/\/www.smashingmagazine.com\/images\/logo\/logo--red.png\"><br \/>\n <span>(gg, yk)<\/span>\n<\/div>\n<\/article>\n","protected":false},"excerpt":{"rendered":"<p>Smashing Animations Part 4: Optimising SVGs Smashing Animations Part 4: Optimising SVGs Andy Clarke 2025-06-04T08:00:00+00:00 2025-06-05T21:02:28+00:00 SVG animations take me back to the Hanna-Barbera cartoons I watched as a kid. Shows like Wacky Races, The Perils of Penelope Pitstop, and, of course, Yogi Bear. They inspired me to lovingly recreate some classic Toon Titles using…<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[11],"tags":[],"_links":{"self":[{"href":"http:\/\/www.computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/posts\/933"}],"collection":[{"href":"http:\/\/www.computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/comments?post=933"}],"version-history":[{"count":1,"href":"http:\/\/www.computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/posts\/933\/revisions"}],"predecessor-version":[{"id":934,"href":"http:\/\/www.computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/posts\/933\/revisions\/934"}],"wp:attachment":[{"href":"http:\/\/www.computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/media?parent=933"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/categories?post=933"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.computercoursesonline.com\/index.php\/wp-json\/wp\/v2\/tags?post=933"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}