<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>COMPUTERCOURSESONLINE</title>
	<atom:link href="http://www.computercoursesonline.com/index.php/feed" rel="self" type="application/rss+xml" />
	<link>http://computercoursesonline.com</link>
	<description></description>
	<lastBuildDate>Thu, 19 Jun 2025 21:05:55 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.9.2</generator>
	<item>
		<title>CSS Cascade Layers Vs. BEM Vs. Utility Classes: Specificity Control</title>
		<link>http://computercoursesonline.com/index.php/2025/06/19/css-cascade-layers-vs-bem-vs-utility-classes-specificity-control/</link>
					<comments>http://computercoursesonline.com/index.php/2025/06/19/css-cascade-layers-vs-bem-vs-utility-classes-specificity-control/#respond</comments>
		
		<dc:creator><![CDATA[.]]></dc:creator>
		<pubDate>Thu, 19 Jun 2025 15:00:00 +0000</pubDate>
				<category><![CDATA[Css]]></category>
		<guid isPermaLink="false">http://computercoursesonline.com/?p=947</guid>

					<description><![CDATA[CSS Cascade Layers Vs. BEM Vs. Utility Classes: Specificity Control CSS Cascade Layers Vs. BEM Vs. Utility Classes: Specificity Control Victor Ayomipo 2025-06-19T15:00:00+00:00 2025-06-19T20:32:57+00:00 CSS is wild, really wild. And tricky. But let’s talk specifically about specificity. When writing CSS, it’s close to impossible that you haven’t faced the frustration of styles not applying as...]]></description>
										<content:encoded><![CDATA[<p>              <title>CSS Cascade Layers Vs. BEM Vs. Utility Classes: Specificity Control</title></p>
<article>
<header>
<h1>CSS Cascade Layers Vs. BEM Vs. Utility Classes: Specificity Control</h1>
<address>Victor Ayomipo</address>
<p>                  2025-06-19T15:00:00+00:00<br />
                  2025-06-19T20:32:57+00:00<br />
                </header>
<p>CSS is wild, really wild. And tricky. But let’s talk specifically about <strong>specificity</strong>.</p>
<p>When writing CSS, it’s close to impossible that you haven’t faced the frustration of styles not applying as expected &mdash; that’s specificity. You applied a style, it worked, and later, you try to override it with a different style and… nothing, it just ignores you. Again, specificity.</p>
<p>Sure, there’s the option of resorting to <code>!important</code> flags, but like all developers before us, it’s always <a href="https://cssguidelin.es/#important">risky and discouraged</a>. It’s way better to fully understand specificity than go down that route because otherwise you wind up fighting your own important styles.</p>
<h2 id="specificity-101">Specificity 101</h2>
<p>Lots of developers understand the concept of specificity in different ways.</p>
<blockquote><p>The core idea of specificity is that the CSS Cascade algorithm used by browsers determines which style declaration is applied when two or more rules match the same element.</p></blockquote>
<p>Think about it. As a project expands, so do the specificity challenges. Let’s say Developer A adds <code>.cart-button</code>, then maybe the button style looks good to be used on the sidebar, but with a little tweak. Then, later, Developer B adds <code>.cart-button .sidebar</code>, and from there, any future changes applied to <code>.cart-button</code> might get overridden by <code>.cart-button .sidebar</code>, and just like that, the specificity war begins.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/1-specificity-tension.png"></p>
<p>    <img loading="lazy" width="800" height="500" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Specifity tension represented by a pile of different elements" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/1-specificity-tension.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      (<a href="https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/1-specificity-tension.png">Large preview</a>)<br />
    </figcaption></figure>
<p>I’ve written CSS long enough to witness different strategies that developers have used to manage the specificity battles that come with CSS.</p>
<pre><code class="language-css">/&#042; Traditional approach &#042;/
#header .nav li a.active { color: blue; }

/&#042; BEM approach &#042;/
.header__nav-item--active { color: blue; }

/&#042; Utility classes approach &#042;/
.text-blue { color: blue; }

/&#042; Cascade Layers approach &#042;/
@layer components {
  .nav-link.active { color: blue; }
}
</code></pre>
<p>All these methods reflect different strategies on how to control or at least maintain CSS specificity:</p>
<ul>
<li><strong>BEM</strong>: tries to simplify specificity by being explicit.</li>
<li><strong>Utility-first CSS</strong>: tries to bypass specificity by keeping it all atomic.</li>
<li><strong>CSS Cascade Layers</strong>: manage specificity by organizing styles in layered groups.</li>
</ul>
<p>We’re going to put all three side by side and look at how they handle specificity.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/2-different-strategies-control-css-specificity.png"></p>
<p>    <img loading="lazy" width="800" height="500" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="A chart which ilustrates different strategies on how to control or at least maintain CSS specificity" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/2-different-strategies-control-css-specificity.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      (<a href="https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/2-different-strategies-control-css-specificity.png">Large preview</a>)<br />
    </figcaption></figure>
<div data-audience="non-subscriber" data-remove="true" class="feature-panel-container">
<aside class="feature-panel">
<div class="feature-panel-left-col">
<div class="feature-panel-description">
<p>Meet <strong><a data-instant href="https://www.smashingconf.com/online-workshops/">Smashing Workshops</a></strong> on <strong>front-end, design &amp; UX</strong>, with practical takeaways, live sessions, <strong>video recordings</strong> and a friendly Q&amp;A. With Brad Frost, Stéph Walter and <a href="https://smashingconf.com/online-workshops/workshops">so many others</a>.</p>
<p><a data-instant href="smashing-workshops" class="btn btn--green btn--large">Jump to the workshops&nbsp;↬</a></div>
</div>
<div class="feature-panel-right-col"><a data-instant href="smashing-workshops" class="feature-panel-image-link"></p>
<div class="feature-panel-image">
<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>
</div>
<p></a>
</div>
</aside>
</div>
<h2 id="my-relationship-with-specificity">My Relationship With Specificity</h2>
<p>I actually used to think that I got the whole picture of CSS specificity. Like the usual inline greater than ID greater than class greater than tag. But, reading <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascade/Cascade">the MDN docs on how the CSS Cascade truly works</a> was an eye-opener.</p>
<p>There’s a code I worked on in an old codebase provided by a client, which looked something like this:</p>
<pre><code class="language-css">/&#042; Legacy code &#042;/
&#035;main-content .product-grid button.add-to-cart {
  background-color: #3a86ff;
  color: white;
  padding: 10px 15px;
  border-radius: 4px;
}

/&#042; 100 lines of other code here &#042;/

/&#042; My new CSS &#042;/
.btn-primary {
  background-color: #4361ee; /&#042; New brand color &#042;/
  color: white;
  padding: 12px 20px;
  border-radius: 4px;
  box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
</code></pre>
<p>Looking at this code, no way that the <code>.btn-primary</code> class stands a chance against whatever specificity chain of selectors was previously written. As far as specification goes, CSS gives the first selector a specificity score of <code>1, 2, 1</code>: one point for the ID, two points for the two classes, and one point for the element selector. Meanwhile, the second selector is scored as <code>0, 1, 0</code> since it only consists of a single class selector.</p>
<p>Sure, I had some options:</p>
<ul>
<li>I could <strong>use <code>!important</code> on the properties</strong> in <code>.btn-primary</code> to override the ones declared in the stronger selector, but the moment that happens, be prepared to use it everywhere. So, I’d rather avoid it.</li>
<li>I could try <strong>going more specific</strong>, but personally, that’s just being cruel to the next developer (who might even be me).</li>
<li>I could <strong>change the styles of the existing code</strong>, but that’s adding to the specificity problem:</li>
</ul>
<pre><code class="language-css">&#035;main-content .product-grid .btn-primary {
  /&#042; edit styles directly &#042;/
}
</code></pre>
<p>Eventually, I ended up writing the whole CSS from scratch.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/3-legacy-modern-button.png"></p>
<p>    <img loading="lazy" width="800" height="500" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Legacy button vs modern button" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/3-legacy-modern-button.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      (<a href="https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/3-legacy-modern-button.png">Large preview</a>)<br />
    </figcaption></figure>
<p>When <em>nesting</em> was introduced, I tried it to control specificity that way:</p>
<div class="break-out">
<pre><code class="language-css">.profile-widget {
  // ... other styles
  .header {
    // ... header styles
    .user-avatar {
      border: 2px solid blue;
      &amp;.is-admin {
        border-color: gold; // This becomes .profile-widget .header .user-avatar.is-admin
      }
    }
  }
}
</code></pre>
</div>
<p>And just like that, I have unintentionally created high-specificity rules. That’s how easily and naturally we can drift toward specificity complexities.</p>
<p>So, to save myself a lot of these issues, I have one principle I always abide by: <a href="https://css-tricks.com/strategies-keeping-css-specificity-low/"><strong>keep specificity as low as possible</strong></a>. And if the selector complexity is becoming a complex chain, I rethink the whole thing.</p>
<div class="partners__lead-place"></div>
<h2 id="bem-the-og-system">BEM: The OG System</h2>
<p>The Block-Element-Modifier (BEM, for short) has been around the block (pun intended) for a long time. It is a methodological system for writing CSS that forces you to make every style hierarchy explicit.</p>
<pre><code class="language-css">/&#042; Block &#042;/
.panel {}

/&#042; Element that depends on the Block &#042;/
.panel&#095;&#095;header {}
.panel&#095;&#095;content {}
.panel&#095;&#095;footer {}

/&#042; Modifier that changes the style of the Block &#042;/
.panel--highlighted {}
.panel&#095;&#095;button--secondary {}
</code></pre>
<p>When I first experienced BEM, I thought it was amazing, despite contrary opinions that it looked ugly. I had no problems with the double hyphens or underscores because they made my CSS predictable and simplified.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/4-bem.png"></p>
<p>    <img loading="lazy" width="800" height="500" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Illustration for BEM methodological system" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/4-bem.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      (<a href="https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/4-bem.png">Large preview</a>)<br />
    </figcaption></figure>
<h3 id="how-bem-handles-specificity">How BEM Handles Specificity</h3>
<p>Take a look at these examples. Without BEM:</p>
<pre><code class="language-css">/&#042; Specificity: 0, 3, 0 &#042;/
.site-header .main-nav .nav-link {
  color: &#035;472EFE;
  text-decoration: none;
}

/&#042; Specificity: 0, 2, 0 &#042;/
.nav-link.special {
  color: &#035;FF5733;
}
</code></pre>
<p>With BEM:</p>
<pre><code class="language-css">/&#042; Specificity: 0, 1, 0 &#042;/
.main-nav&#095;&#095;link {
  color: &#035;472EFE;
  text-decoration: none;
}

/&#042; Specificity: 0, 1, 0 &#042;/
.main-nav&#095;&#095;link--special {
  color: &#035;FF5733;
}
</code></pre>
<p>You see how BEM makes the code look predictable as all selectors are created equal, thus making the code easier to maintain and extend. And if I want to add a button to <code>.main-nav</code>, I just add <code>.main-nav__btn</code>, and if I need a disabled button (modifier), <code>.main-nav__btn--disabled</code>. Specificity is low, as I don’t have to increase it or fight the cascade; I just write a new class.</p>
<p>BEM’s naming principle made sure components lived in isolation, which, for a part of CSS, the specificity part, it worked, i.e, <code>.card__title</code> class will never accidentally clash with a <code>.menu__title</code> class.</p>
<h3 id="where-bem-falls-short">Where BEM Falls Short</h3>
<p>I like the idea of BEM, but it is not perfect, and a lot of people noticed it:</p>
<ul>
<li>The class names can get <em>really</em> long.</li>
</ul>
<div class="break-out">
<pre><code class="language-html">&lt;div class="product-carousel&#095;&#095;slide--featured product-carousel&#095;&#095;slide--on-sale"&gt;
  &lt;!-- yikes --&gt;
&lt;/div&gt;
</code></pre>
</div>
<ul>
<li><strong>Reusability might not be prioritized</strong>, which somewhat contradicts the native CSS ideology. Should a button inside a card be <code>.card__button</code> or reuse a global <code>.button</code> class? With the former, styles are being duplicated, and with the latter, the BEM strict model is being broken.</li>
<li>One of the core pains in software development starts becoming a reality &mdash; <strong>naming things</strong>. <a href="https://css-tricks.com/naming-things-is-only-getting-harder/">I’m sure you know the frustration of that already.</a></li>
</ul>
<p>BEM is good, but sometimes you may need to be flexible with it. A <strong>hybrid system</strong> (maybe using BEM for core components but simpler classes elsewhere) can still keep specificity as low as needed.</p>
<pre><code class="language-css">/&#042; Base button without BEM &#042;/
.button {
  /&#042; Button styles &#042;/
}

/&#042; Component-specific button with BEM &#042;/
.card&#095;&#095;footer .button {
  /&#042; Minor overrides &#042;/
}
</code></pre>
<h2 id="utility-classes-specificity-by-avoidance">Utility Classes: Specificity By Avoidance</h2>
<p>This is also called <a href="https://css-tricks.com/lets-define-exactly-atomic-css/">Atomic CSS</a>. And in its entirety, it <em>avoids specificity.</em></p>
<div class="break-out">
<pre><code class="language-html">&lt;button class="bg-red-300 hover:bg-red-500 text-white py-2 px-4 rounded"&gt;
  A button
&lt;/button&gt;
</code></pre>
</div>
<blockquote><p>The idea behind utility-first classes is that every utility class has the same specificity, which is one class selector. Each class is a tiny CSS property with a single purpose.</p></blockquote>
<p><code>p-2</code>? Padding, nothing more. <code>text-red</code>? Color red for text. <code>text-center</code>? Text alignment. It’s like how LEGOs work, but for styling. You stack classes on top of each other until you get your desired appearance.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/5-specificity-by-avoidance.png"></p>
<p>    <img loading="lazy" width="800" height="500" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="An illustration with a title: Avoiding specifity - one utility at a time" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/5-specificity-by-avoidance.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      (<a href="https://files.smashing.media/articles/css-cascade-layers-bem-utility-classes-specificity-control/5-specificity-by-avoidance.png">Large preview</a>)<br />
    </figcaption></figure>
<h3 id="how-utility-classes-handle-specificity">How Utility Classes Handle Specificity</h3>
<p>Utility classes do not solve specificity, but rather, they take the BEM ideology of low specificity to the extreme. Almost all utility classes have the same lowest possible specificity level of (<code>0</code>, <code>1</code>, <code>0</code>). And because of this, overrides become easy; if more padding is needed, bump <code>.p-2</code> to <code>.p-4</code>.</p>
<p>Another example:</p>
<pre><code class="language-html">&lt;button class="bg-orange-300 hover:bg-orange-700"&gt;
  This can be hovered
&lt;/button&gt;
</code></pre>
<p>If another class, <code>hover:bg-red-500</code>, is added, the order matters for CSS to determine which to use. So, even though the utility classes avoid specificity, the other parts of the CSS Cascade come in, which is the order of appearance, with the last matching selector declared being the winner.</p>
<h3 id="utility-class-trade-offs">Utility Class Trade-Offs</h3>
<p>The most common issue with utility classes is that <strong>they make the code look ugly</strong>. And frankly, I agree. But being able to picture what a component looks like without seeing it rendered is just priceless.</p>
<p>There’s also the argument of reusability, that you repeat yourself every single time. But once one finds a repetition happening, just turn that part into a reusable component. It also has its genuine <strong>limitations</strong> when it comes to specificity:</p>
<ul>
<li>If your brand color changes, which is a global change, and you’re deep in the codebase, you can’t just change one and have others follow like native CSS.</li>
<li>The parent-child relationship that happens naturally in native CSS is out the window due to how atomic utility classes behave.</li>
<li>Some argue the HTML part should be left as markup and the CSS part for styling. Because now, there’s more markup to scan, and if you decide to clean up:</li>
</ul>
<div class="break-out">
<pre><code class="language-html">&lt;!-- Too long --&gt;
&lt;div class="p-4 bg-yellow-100 border border-yellow-300 text-yellow-800 rounded"&gt;

&lt;!-- Better? --&gt;
&lt;div class="alert-warning"&gt;
</code></pre>
</div>
<p>Just like that, we’ve ended up writing CSS. Circle of life.</p>
<p>In my experience with utility classes, they work best for:</p>
<ul>
<li><strong>Speed</strong><br />
Writing the markup, styling it, and seeing the result swiftly.</li>
<li><strong>Predictability</strong><br />
A utility class does exactly what it says it does.</li>
</ul>
<h2 id="cascade-layers-specificity-by-design">Cascade Layers: Specificity By Design</h2>
<p>Now, this is where it gets interesting. BEM offers structure, utility classes gain speed, and CSS Cascade Layers give us something paramount: <strong>control</strong>.</p>
<p>Anyways, Cascade Layers (<code>@layers</code>) groups styles and declares what order the groups should be, regardless of the specificity scores of those rules.</p>
<p>Looking at a set of independent rulesets:</p>
<pre><code class="language-css">button {
  background-color: orange; /&#042; Specificity: 0, 0, 1 &#042;/
}

.button {
  background-color: blue; //&#042; Specificity: 0, 1, 0&#042;/
}

#button {
  background-color: red; /&#042; Specificity: 1, 0, 0 &#042;/
}

/&#042; No matter what, the button is red &#042;/
</code></pre>
<p>But with <code>@layer</code>, let’s say, I want to prioritize the <code>.button</code> class selector. I can shape how the specificity order should go:</p>
<pre><code class="language-css">@layer utilities, defaults, components;

@layer defaults {
  button {
    background-color: orange; /&#042; Specificity: 0, 0, 1 &#042;/
  }
}

@layer components {
  .button {
    background-color: blue; //&#042; Specificity: 0, 1, 0&#042;/
  }
}

@layer utilities {
  #button {
    background-color: red; /&#042; Specificity: 1, 0, 0 &#042;/
  }
}
</code></pre>
<p>Due to how <code>@layer</code> works, <code>.button</code> would win because the <code>components</code> layer is the highest priority, even though <code>#button</code> has higher specificity. Thus, before CSS could even check the usual specificity rules, the layer order would first be respected.</p>
<p>You just have to respect the folks over at W3C, because now one can purposely override an ID selector with a simple class, without even using <code>!important</code>. Fascinating.</p>
<h3 id="cascade-layers-nuances">Cascade Layers Nuances</h3>
<p>Here are some things that are worth calling out when we’re talking about CSS Cascade Layers:</p>
<ul>
<li>Specificity is still part of the game.</li>
<li><code>!important</code> acts differently than expected in <code>@layer</code> (they work in reverse!).</li>
<li><code>@layers</code> aren’t selector-specific but rather style-property-specific.</li>
</ul>
<div class="break-out">
<pre><code class="language-css">@layer base {
  .button {
    background-color: blue;
    color: white;
  }
}

@layer theme {
  .button {
    background-color: red;
    /&#042; No color property here, so white from base layer still applies &#042;/
  }
}
</code></pre>
</div>
<ul>
<li><code>@layer</code> can easily be abused. I’m sure there’s a developer out there with over 20+ layer declarations that’s grown into a monstrosity.</li>
</ul>
<h3 id="comparing-all-three">Comparing All Three</h3>
<p>Now, for the TL;DR folks out there, here’s a side-by-side comparison of the three: BEM, utility classes, and CSS Cascade Layers.</p>
<table class="tablesaw break-out">
<thead>
<tr>
<th>Feature</th>
<th>BEM</th>
<th>Utility Classes</th>
<th>Cascade Layers</th>
</tr>
</thead>
<tbody>
<tr>
<td>Core Idea</td>
<td>Namespace components</td>
<td>Single purpose classes</td>
<td>Control cascade order</td>
</tr>
<tr>
<td>Specificity Control</td>
<td>Low and flat</td>
<td>Avoids entirely</td>
<td>Absolute control due to Layer supremacy</td>
</tr>
<tr>
<td>Code Readability</td>
<td>Clear structure due to naming</td>
<td>Unclear if unfamiliar with the class names</td>
<td>Clear if layer structure is followed</td>
</tr>
<tr>
<td>HTML Verbosity</td>
<td>Moderate class names (can get long)</td>
<td>Many small classes that adds up quickly</td>
<td>No direct impact, stays only in CSS</td>
</tr>
<tr>
<td>CSS Organization</td>
<td>By component</td>
<td>By property</td>
<td>By priority order</td>
</tr>
<tr>
<td>Learning Curve</td>
<td>Requires understanding conventions</td>
<td>Requires knowing the utility names</td>
<td>Easy to pick up, but requires a deep understanding of CSS</td>
</tr>
<tr>
<td>Tools Dependency</td>
<td>Pure CSS</td>
<td>Often depends of third-party e.g Tailwind</td>
<td>Native CSS</td>
</tr>
<tr>
<td>Refactoring Ease</td>
<td>High</td>
<td>Medium</td>
<td>Low</td>
</tr>
<tr>
<td>Best Use Case</td>
<td>Design Systems</td>
<td>Fast builds</td>
<td>Legacy code or third-party codes that need overrides</td>
</tr>
<tr>
<td>Browser Support</td>
<td>All</td>
<td>All</td>
<td>All (except IE)</td>
</tr>
</tbody>
</table>
<p>Among the three, each has its sweet spot:</p>
<ul>
<li><strong>BEM</strong> is best when:
<ul>
<li>There’s a clear design system that needs to be consistent,</li>
<li>There’s a team with different philosophies about CSS (BEM can be the middle ground), and</li>
<li>Styles are less likely to leak between components.</li>
</ul>
</li>
<li><strong>Utility classes</strong> work best when:
<ul>
<li>You need to build fast, like prototypes or MVPs, and</li>
<li>Using a component-based JavaScript framework like React.</li>
</ul>
</li>
<li><strong>Cascade Layers</strong> are most effective when:
<ul>
<li>Working on legacy codebases where you need full specificity control,</li>
<li>You need to integrate third-party libraries or styles from different sources, and</li>
<li>Working on a large, complex application or projects with long-term maintenance.</li>
</ul>
</li>
</ul>
<p>If I had to choose or rank them, I’d go for utility classes with Cascade Layers over using BEM. But that’s just me!</p>
<div class="partners__lead-place"></div>
<h2 id="where-they-intersect-how-they-can-work-together">Where They Intersect (How They Can Work Together)</h2>
<p>Among the three, Cascade Layers should be seen as an orchestrator, as it can work with the other two strategies. <code>@layer</code> is a fundamental tenet of the CSS Cascade’s architecture, unlike BEM and utility classes, which are methodologies for controlling the Cascade’s behavior.</p>
<pre><code class="language-css">/&#042; Cascade Layers + BEM &#042;/
@layer components {
  .card&#095;&#095;title {
    font-size: 1.5rem;
    font-weight: bold;
  }
}

/&#042; Cascade Layers + Utility Classes &#042;/
@layer utilities {
  .text-xl {
    font-size: 1.25rem;
  }
  .font-bold {
    font-weight: 700;
  }
}
</code></pre>
<p>On the other hand, using BEM with utility classes would just end up clashing:</p>
<div class="break-out">
<pre><code class="language-javascript">&lt;!-- This feels wrong --&gt;
&lt;div class="card__container p-4 flex items-center"&gt;
  &lt;p class="card__title text-xl font-bold"&gt;Something seems wrong&lt;/p&gt;
&lt;/div&gt;
</code></pre>
</div>
<p>I’m putting all my cards on the table: I’m a utility-first developer. And most utility class frameworks use <code>@layer</code> behind the scenes (e.g., <a href="https://tailwindcss.com/blog/tailwindcss-v4#designed-for-the-modern-web">Tailwind</a>). So, those two are already together in the bag.</p>
<p>But, do I dislike BEM? Not at all! I’ve used it a lot and still would, if necessary. I just find naming things to be an exhausting exercise.</p>
<p>That said, we’re all different, and you might have opposing thoughts about what you think feels best. It truly doesn’t matter, and that’s the beauty of this web development space. <em>Multiple routes can lead to the same destination</em>.</p>
<h2 id="conclusion">Conclusion</h2>
<p>So, when it comes to comparing BEM, utility classes, and CSS Cascade Layers, is there a true “winning” approach for controlling specificity in the Cascade?</p>
<p>First of all, CSS Cascade Layers are arguably the most powerful CSS feature that we’ve gotten in years. They shouldn’t be confused with BEM or utility classes, which are strategies rather than part of the CSS feature set.</p>
<p>That’s why I like the idea of combining either BEM with Cascade Layers or utility classes with Cascade Layers. Either way, the idea is to <strong>keep specificity low and leverage Cascade Layers to set priorities on those styles</strong>.</p>
<div class="signature">
  <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 />
  <span>(gg, yk)</span>
</div>
</article>
]]></content:encoded>
					
					<wfw:commentRss>http://computercoursesonline.com/index.php/2025/06/19/css-cascade-layers-vs-bem-vs-utility-classes-specificity-control/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Meet Accessible UX Research, A Brand-New Smashing Book</title>
		<link>http://computercoursesonline.com/index.php/2025/06/18/meet-accessible-ux-research-a-brand-new-smashing-book/</link>
					<comments>http://computercoursesonline.com/index.php/2025/06/18/meet-accessible-ux-research-a-brand-new-smashing-book/#respond</comments>
		
		<dc:creator><![CDATA[.]]></dc:creator>
		<pubDate>Wed, 18 Jun 2025 16:00:00 +0000</pubDate>
				<category><![CDATA[Ux]]></category>
		<guid isPermaLink="false">http://computercoursesonline.com/?p=949</guid>

					<description><![CDATA[Meet Accessible UX Research, A Brand-New Smashing Book Meet Accessible UX Research, A Brand-New Smashing Book Vitaly Friedman 2025-06-18T16:00:00+00:00 2025-06-19T20:32:57+00:00 UX research can take so much of the guesswork out of the design process! But it’s easy to forget just how different people are and how their needs and preferences can vary. We can’t predict...]]></description>
										<content:encoded><![CDATA[<p>              <title>Meet Accessible UX Research, A Brand-New Smashing Book</title></p>
<article>
<header>
<h1>Meet Accessible UX Research, A Brand-New Smashing Book</h1>
<address>Vitaly Friedman</address>
<p>                  2025-06-18T16:00:00+00:00<br />
                  2025-06-19T20:32:57+00:00<br />
                </header>
<p><strong>UX research</strong> can take so much of the guesswork out of the design process! But it’s easy to forget just how <em>different</em> people are and how their needs and preferences can vary. We can’t predict the needs of every user, but we shouldn’t expect different people using the product in roughly the same way. That’s how we end up with an incomplete, inaccurate, or simply wrong picture of our customers.</p>
<p>There is no shortage of accessibility checklists and guidelines. But accessibility isn’t a checklist. It doesn’t happen by accident. It’s a <strong>dedicated effort</strong> to include and consider and understand different needs of different users to make sure everyone can use our products successfully. That’s why we’ve teamed up with Michele A. Williams on a shiny new book around just that.</p>
<p>Meet <em>Accessible UX Research</em>, your guide to <strong>making UX research more inclusive</strong> of participants with different needs — from planning and recruiting to facilitation, asking better questions, avoiding bias, and building trust. <a href="/printed-books/accessible-ux-research/" data-product-sku="accessible-ux-research" data-component="AddToCart" data-product-path="/printed-books/accessible-ux-research" data-silent="true">Pre-order the book.</a></p>
<figure style="margin-bottom:0;padding-bottom:0" class="break-out article__image">
    <a href="https://files.smashing.media/articles/accessible-ux-research-pre-release/accessible-ux-research-coming-soon-light-opt.png" title="Tap for a large preview of the book."><br />
    <img loading="lazy" width="900" height="506" style="border-radius: 11px" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Illustration showing Smashing Magazine’s mascot Topple, a red, cartoon-style cat wearing a black sweater. It is smiling and holding a post-it note in its right hand that reads “New” as it is peeking from behind Michele A. William’s new book “Accessible UX Research”. The book has a teal cover that shows a three times three grid of windows in different architectural styles. Inside the windows, there are icons related to UX research, such as speech bubbles, a looking glass, a keyboard, and UI components. The text on the illustration reads: “Coming soon to the Smashing Library! Pre-order your copy now.”" class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/06/accessible-ux-research-coming-soon-light-varnish-opt.png"><br />
    </a><br />
</figure>
<div class="book-cta__inverted">
<div class="book-cta" data-handler="ContentTabs" data-mq="(max-width: 480px)">
<nav class="content-tabs content-tabs--books">
<ul>
<li class="content-tab">
      <a href="#"><br />
        <button class="btn btn--small btn--white btn--white--bordered"><br />
          Print + eBook<br />
        </button><br />
      </a>
    </li>
<li class="content-tab">
      <a href="#"><br />
        <button class="btn btn--small btn--white btn--white--bordered"><br />
          eBook<br />
        </button><br />
      </a>
    </li>
</ul>
</nav>
<div class="book-cta__col book-cta__hardcover content-tab--content">
<h3 class="book-cta__title">
			<span>Print + eBook</span><br />
		</h3>
<p>	{<br />
		&#8220;sku&#8221;: &#8220;accessible-ux-research&#8221;,<br />
		&#8220;type&#8221;: &#8220;Book&#8221;,<br />
		&#8220;price&#8221;: &#8220;44.00&#8221;,</p>
<p>		&#8220;prices&#8221;: [{<br />
			&#8220;amount&#8221;: &#8220;44.00&#8221;,<br />
			&#8220;currency&#8221;: &#8220;USD&#8221;,<br />
			&#8220;items&#8221;: [<br />
				{&#8220;amount&#8221;: &#8220;34.00&#8221;, &#8220;type&#8221;: &#8220;Book&#8221;},<br />
				{&#8220;amount&#8221;: &#8220;10.00&#8221;, &#8220;type&#8221;: &#8220;E-Book&#8221;}<br />
			]<br />
		}, {<br />
			&#8220;amount&#8221;: &#8220;44.00&#8221;,<br />
			&#8220;currency&#8221;: &#8220;EUR&#8221;,<br />
			&#8220;items&#8221;: [<br />
				{&#8220;amount&#8221;: &#8220;34.00&#8221;, &#8220;type&#8221;: &#8220;Book&#8221;},<br />
				{&#8220;amount&#8221;: &#8220;10.00&#8221;, &#8220;type&#8221;: &#8220;E-Book&#8221;}<br />
			]<br />
		}<br />
		]<br />
	}</p>
<p><span class="book-cta__price" data-handler="PriceTag" data-sku="accessible-ux-research" data-type="Book" data-insert="true"><br />
  <span class="placeholder"></p>
<p><span class="currency-sign">$</span><br />
44<span class="sup">.00</span></p>
<p>  </span><br />
</span></p>
<p>		<button class="btn btn--full btn--medium btn--text-shadow" data-product-path="/printed-books/accessible-ux-research/" data-product-sku="accessible-ux-research" data-author="Michele Williams" data-authors="" data-link="" data-component="AddToCart"><br />
			 Get Print + eBook<br />
		</button></p>
<p class="book-cta__desc">
			Quality hardcover. <a href="https://www.smashingmagazine.com/delivery-times/">Free worldwide shipping starting in August 2025</a>.<br /> 100 days money-back-guarantee.
		</p>
</p></div>
<div class="book-cta__col book-cta__ebook content-tab--content">
<h3 class="book-cta__title">
			<span>eBook</span><br />
		</h3>
<div data-audience="anonymous free supporter" data-remove="true">
<p>	{<br />
		&#8220;sku&#8221;: &#8220;accessible-ux-research-ebook&#8221;,<br />
		&#8220;type&#8221;: &#8220;E-Book&#8221;,<br />
		&#8220;price&#8221;: &#8220;19.00&#8221;,</p>
<p>		&#8220;prices&#8221;: [{<br />
			&#8220;amount&#8221;: &#8220;19.00&#8221;,<br />
			&#8220;currency&#8221;: &#8220;USD&#8221;<br />
		}, {<br />
			&#8220;amount&#8221;: &#8220;19.00&#8221;,<br />
			&#8220;currency&#8221;: &#8220;EUR&#8221;<br />
		}<br />
		]<br />
	}</p>
<p><span class="book-cta__price" data-handler="PriceTag" data-sku="accessible-ux-research-ebook" data-type="E-Book" data-insert="true"><br />
  <span class="placeholder"></p>
<p><span class="currency-sign">$</span><br />
19<span class="sup">.00</span></p>
<p>  </span><br />
</span></p></div>
<p>      <span class="book-cta__price hidden" data-audience="smashing member" data-remove="true"><br />
        <span class="green">Free!</span><br />
      </span></p>
<p>		<button class="btn btn--full btn--medium btn--text-shadow" data-product-path="/printed-books/accessible-ux-research/" data-product-sku="accessible-ux-research-ebook" data-author="Michele Williams" data-authors="" data-link="" data-component="AddToCart" data-audience="anonymous free supporter" data-remove="true"><br />
			  Get the eBook<br />
		</button></p>
<p class="book-cta__desc" data-audience="anonymous free supporter" data-remove="true">
			DRM-free, of course. ePUB, Kindle, PDF available for download later this summer.<br />Included with your <a href="https://www.smashingmagazine.com/membership/">Smashing Membership.</a>
		</p>
<div data-audience="smashing member" class="hidden" data-remove="true">
    <a href="accessibleresearchpdf" class="btn btn--medium btn--green btn--full js-add-to-cart"><br />
      Get the eBook<br />
    </a></p>
<p class="book-cta__desc book-cta__desc--light">
      <a href="accessibleresearchpdf">Download PDF</a>, <a href="accessibleresearchepub">ePUB</a>, <a href="accessibleresearchmobi">Kindle</a>.<br />Thanks for being smashing!&nbsp;<img src="https://s.w.org/images/core/emoji/13.1.0/72x72/2764.png" alt="❤" class="wp-smiley" style="height: 1em; max-height: 1em;" />
    </p>
</p></div>
</p></div>
</div>
</div>
<h2 id="about-the-book">About The Book</h2>
<p>The book isn’t a checklist for you to complete as a part of your accessibility work. It’s a <strong>practical guide to inclusive UX research</strong>, from start to finish. If you’ve ever felt unsure how to include disabled participants, or worried about “getting it wrong,” this book is for you. You’ll get clear, practical strategies to make your research more inclusive, effective, and reliable.</p>
<p>Inside, you’ll learn how to:</p>
<ul>
<li><strong>Plan research</strong> that includes disabled participants from the start,</li>
<li><strong>Recruit participants</strong> with disabilities,</li>
<li><strong>Facilitate sessions</strong> that work for a range of access needs,</li>
<li><strong>Ask better questions</strong> and avoid unintentionally biased research methods,</li>
<li><strong>Build trust and confidence</strong> in your team around accessibility and inclusion.</li>
</ul>
<p>The book also challenges common assumptions about disability and urges readers to <strong>rethink what inclusion really means</strong> in UX research and beyond. Let’s move beyond compliance and start doing research that reflects the full diversity of your users. Whether you’re in industry or academia, this book gives you the tools — and the mindset — to make it happen.</p>
<p>High-quality hardcover. Written by Dr. Michele A. Williams. Cover art by Espen Brunborg. <strong>Print shipping in August 2025. eBook available for download later this summer.</strong> <a href="/printed-books/accessible-ux-research/" data-product-sku="accessible-ux-research" data-component="AddToCart" data-product-path="/printed-books/accessible-ux-research" data-silent="true">Pre-order the book.</a></p>
<h2 id="contents">Contents</h2>
<ol>
<li><strong>Disability mindset</strong>: For inclusive research to succeed, we must first confront our mindset about disability, typically influenced by ableism.</li>
<li><strong>Diversity of disability</strong>: Accessibility is not solely about blind screen reader users; disability categories help us unpack and process the diversity of disabled users.</li>
<li><strong>Disability in the stages of UX research</strong>: Disabled participants can and should be part of every research phase — formative, prototype, and summative.</li>
<li><strong>Recruiting disabled participants</strong>: Recruiting disabled participants is not always easy, but that simply means we need to learn strategies on where to look.</li>
<li><strong>Designing your research</strong>: While our goal is to influence accessible products, our research execution must also be accessible.</li>
<li><strong>Facilitating an accessible study</strong>: Preparation and communication with your participants can ensure your study logistics run smoothly.</li>
<li><strong>Analyzing and reporting with accuracy and impact</strong>: How you communicate your findings is just as important as gathering them in the first place — so prepare to be a storyteller, educator, and advocate.</li>
<li><strong>Disability in the UX research field</strong>: Inclusion isn’t just for research <em>participants</em>, it’s important for our <em>colleagues</em> as well, as explained by blind UX Researcher Dr. Cynthia Bennett.</li>
</ol>
<h2 id="who-this-book-is-for">Who This Book Is For</h2>
<p>Whether a UX professional who conducts research in industry or academia, or more broadly part of an engineering, product, or design function, you’ll want to read this book if…</p>
<ol>
<li>You have been tasked to <strong>improve accessibility of your product</strong>, but need to know where to start to facilitate this successfully.</li>
<li>You want to establish a <strong>culture for accessibility</strong> in your company, but not sure how to make it work.</li>
<li>You want to <strong>move from WCAG/EAA compliance</strong> to established accessibility practices and inclusion in research practices and beyond.</li>
<li>You want to <strong>improve your overall accessibility knowledge</strong> and be viewed as an Accessibility Specialist for your organization.</li>
</ol>
<figure style="margin-bottom:0;padding-bottom:0" class="break-out article__image">
    <a href="https://files.smashing.media/articles/accessible-ux-research-pre-release/accessible-ux-research-kind-support-light-opt.png" title="Tap for a large preview of the book."><br />
    <img style="border-radius: 11px" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Illustration showing Smashing Magazine’s mascot Topple, a red, cartoon-style cat wearing a black sweater. It is smiling and holding a post-it note in its right hand that reads “New” as it is peeking from behind Michele A. William’s new book “Accessible UX Research”. The book has a teal cover that shows a three times three grid of windows in different architectural styles. Inside the windows, there are icons related to UX research, such as speech bubbles, a looking glass, a keyboard, and UI components. The text on the illustration reads: “Thanks for your kind support.”" class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/06/accessible-ux-research-kind-support-light-varnish-opt.png"><br />
    </a><br />
</figure>
<div class="book-cta__inverted">
<div class="book-cta" data-handler="ContentTabs" data-mq="(max-width: 480px)">
<nav class="content-tabs content-tabs--books">
<ul>
<li class="content-tab">
      <a href="#"><br />
        <button class="btn btn--small btn--white btn--white--bordered"><br />
          Print + eBook<br />
        </button><br />
      </a>
    </li>
<li class="content-tab">
      <a href="#"><br />
        <button class="btn btn--small btn--white btn--white--bordered"><br />
          eBook<br />
        </button><br />
      </a>
    </li>
</ul>
</nav>
<div class="book-cta__col book-cta__hardcover content-tab--content">
<h3 class="book-cta__title">
			<span>Print + eBook</span><br />
		</h3>
<p>	{<br />
		&#8220;sku&#8221;: &#8220;accessible-ux-research&#8221;,<br />
		&#8220;type&#8221;: &#8220;Book&#8221;,<br />
		&#8220;price&#8221;: &#8220;44.00&#8221;,</p>
<p>		&#8220;prices&#8221;: [{<br />
			&#8220;amount&#8221;: &#8220;44.00&#8221;,<br />
			&#8220;currency&#8221;: &#8220;USD&#8221;,<br />
			&#8220;items&#8221;: [<br />
				{&#8220;amount&#8221;: &#8220;34.00&#8221;, &#8220;type&#8221;: &#8220;Book&#8221;},<br />
				{&#8220;amount&#8221;: &#8220;10.00&#8221;, &#8220;type&#8221;: &#8220;E-Book&#8221;}<br />
			]<br />
		}, {<br />
			&#8220;amount&#8221;: &#8220;44.00&#8221;,<br />
			&#8220;currency&#8221;: &#8220;EUR&#8221;,<br />
			&#8220;items&#8221;: [<br />
				{&#8220;amount&#8221;: &#8220;34.00&#8221;, &#8220;type&#8221;: &#8220;Book&#8221;},<br />
				{&#8220;amount&#8221;: &#8220;10.00&#8221;, &#8220;type&#8221;: &#8220;E-Book&#8221;}<br />
			]<br />
		}<br />
		]<br />
	}</p>
<p><span class="book-cta__price" data-handler="PriceTag" data-sku="accessible-ux-research" data-type="Book" data-insert="true"><br />
  <span class="placeholder"></p>
<p><span class="currency-sign">$</span><br />
44<span class="sup">.00</span></p>
<p>  </span><br />
</span></p>
<p>		<button class="btn btn--full btn--medium btn--text-shadow" data-product-path="/printed-books/accessible-ux-research/" data-product-sku="accessible-ux-research" data-author="Michele Williams" data-authors="" data-link="" data-component="AddToCart"><br />
			 Get Print + eBook<br />
		</button></p>
<p class="book-cta__desc">
			Quality hardcover. <a href="https://www.smashingmagazine.com/delivery-times/">Free worldwide shipping starting in August 2025</a>.<br /> 100 days money-back-guarantee.
		</p>
</p></div>
<div class="book-cta__col book-cta__ebook content-tab--content">
<h3 class="book-cta__title">
			<span>eBook</span><br />
		</h3>
<div data-audience="anonymous free supporter" data-remove="true">
<p>	{<br />
		&#8220;sku&#8221;: &#8220;accessible-ux-research-ebook&#8221;,<br />
		&#8220;type&#8221;: &#8220;E-Book&#8221;,<br />
		&#8220;price&#8221;: &#8220;19.00&#8221;,</p>
<p>		&#8220;prices&#8221;: [{<br />
			&#8220;amount&#8221;: &#8220;19.00&#8221;,<br />
			&#8220;currency&#8221;: &#8220;USD&#8221;<br />
		}, {<br />
			&#8220;amount&#8221;: &#8220;19.00&#8221;,<br />
			&#8220;currency&#8221;: &#8220;EUR&#8221;<br />
		}<br />
		]<br />
	}</p>
<p><span class="book-cta__price" data-handler="PriceTag" data-sku="accessible-ux-research-ebook" data-type="E-Book" data-insert="true"><br />
  <span class="placeholder"></p>
<p><span class="currency-sign">$</span><br />
19<span class="sup">.00</span></p>
<p>  </span><br />
</span></p></div>
<p>      <span class="book-cta__price hidden" data-audience="smashing member" data-remove="true"><br />
        <span class="green">Free!</span><br />
      </span></p>
<p>		<button class="btn btn--full btn--medium btn--text-shadow" data-product-path="/printed-books/accessible-ux-research/" data-product-sku="accessible-ux-research-ebook" data-author="Michele Williams" data-authors="" data-link="" data-component="AddToCart" data-audience="anonymous free supporter" data-remove="true"><br />
			  Get the eBook<br />
		</button></p>
<p class="book-cta__desc" data-audience="anonymous free supporter" data-remove="true">
			DRM-free, of course. ePUB, Kindle, PDF available for download later this summer.<br />Included with your <a href="https://www.smashingmagazine.com/membership/">Smashing Membership.</a>
		</p>
<div data-audience="smashing member" class="hidden" data-remove="true">
    <a href="accessibleresearchpdf" class="btn btn--medium btn--green btn--full js-add-to-cart"><br />
      Get the eBook<br />
    </a></p>
<p class="book-cta__desc book-cta__desc--light">
      <a href="accessibleresearchpdf">Download PDF</a>, <a href="accessibleresearchepub">ePUB</a>, <a href="accessibleresearchmobi">Kindle</a>.<br />Thanks for being smashing!&nbsp;<img src="https://s.w.org/images/core/emoji/13.1.0/72x72/2764.png" alt="❤" class="wp-smiley" style="height: 1em; max-height: 1em;" />
    </p>
</p></div>
</p></div>
</div>
</div>
<h2 id="about-the-author">About the Author</h2>
<p><a href="https://mawconsultingllc.com/"><img loading="lazy" style="float:right;margin-top:1em;margin-left:0.9em;margin-bottom:1em;border-radius:50%;max-width:calc(50% - 5vh);height:auto" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" width="150" height="150" alt="Michele A. Williams" class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/06/michele-williams-opt.png"></a>Dr. Michele A. Williams is owner of <a href="https://mawconsultingllc.com/">M.A.W. Consulting, LLC &#8211; Making Accessibility Work</a>. Her 20+ years of experience include influencing top tech companies as a Senior User Experience (UX) Researcher and Accessibility Specialist and obtaining a PhD in Human-Centered Computing focused on accessibility. An international speaker, <a href="https://scholar.google.com/citations?user=1IfsBJEAAAAJ&amp;hl=en">published academic author</a>, and <a href="https://patents.justia.com/patent/10854103">patented inventor</a>, she is passionate about educating and advising on technology that does not exclude disabled users.</p>
<h2 id="testimonials">Testimonials</h2>
<blockquote style="font-style: normal"><p><img loading="lazy" style="clear:both;float:right;margin-top:0em;margin-left:0.9em;margin-bottom:1em;border-radius:50%;max-width:calc(50% - 5vh);height:auto" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" width="150" height="150" alt="Eric Bailey" class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/06/eric-bailey-opt.png">“<em>Accessible UX Research</em> stands as a vital and necessary resource. In addressing disability at the User Experience Research layer, it helps to set an equal and equitable tone for products and features that resonates through the rest of the creation process. The book provides a <strong>solid framework</strong> for all aspects of conducting research efforts, including not only process considerations, but also importantly the mindset required to approach the work.</p>
<p>This is <strong>the book I wish I had</strong> when I was first getting started with my accessibility journey. It is a gift, and I feel so fortunate that Michele has chosen to share it with us all.”</p>
<p>Eric Bailey, Accessibility Advocate</p></blockquote>
<blockquote style="font-style: normal"><p><img loading="lazy" style="clear:both;float:right;margin-top:0em;margin-left:0.9em;margin-bottom:1em;border-radius:50%;max-width:calc(50% - 5vh);height:auto" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" width="150" height="150" alt="Devon Pershing" class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/06/devon-pershing-opt.png">“User research in accessibility is non-negotiable for actually meeting users’ needs, and this book is a <strong>critical piece in the puzzle</strong> of actually doing and integrating that research into accessibility work day to day.”</p>
<p>Devon Pershing, Author of <em>The Accessibility Operations Guidebook</em></p></blockquote>
<blockquote style="font-style: normal"><p><img loading="lazy" style="clear:both;float:right;margin-top:0em;margin-left:0.9em;margin-bottom:1em;border-radius:50%;max-width:calc(50% - 5vh);height:auto" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" width="150" height="150" alt="Manuel Matuzović" class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/06/manuel-matuzovic-opt.png">“Our decisions as developers and designers are often based on recommendations, assumptions, and biases. Usually, this doesn’t work, because checking off lists or working solely from our own perspective can never truly represent the <strong>depth of human experience</strong>. Michele’s book provides you with the strategies you need to conduct UX research with diverse groups of people, challenge your assumptions, and create truly great products.”</p>
<p>Manuel Matuzović, Author of the <em>Web Accessibility Cookbook</em></p></blockquote>
<blockquote style="font-style: normal"><p><img loading="lazy" style="clear:both;float:right;margin-top:0em;margin-left:0.9em;margin-bottom:1em;border-radius:50%;max-width:calc(50% - 5vh);height:auto" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" width="150" height="150" alt="Anna E. Cook" class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/06/anna-e-cook-opt.png">“This book is a vital resource on inclusive research. Michele Williams expertly breaks down key concepts, guiding readers through disability models, language, and etiquette. A <strong>strong focus on real-world application</strong> equips readers to conduct impactful, inclusive research sessions. By emphasizing diverse perspectives and proactive inclusion, the book makes a compelling case for accessibility as a core principle rather than an afterthought. It is a must-read for researchers, product-makers, and advocates!”</p>
<p>Anna E. Cook, Accessibility and Inclusive Design Specialist</p></blockquote>
<h2 id="technical-details">Technical Details</h2>
<ul>
<li>ISBN: <span class="small-caps">978-3-910835-03-0</span> (print)</li>
<li><strong>Quality hardcover</strong>, stitched binding, ribbon page marker.</li>
<li>Free worldwide airmail <strong>shipping from Germany starting in August 2025</strong>.</li>
<li>eBook available for download as <strong>PDF, ePUB, and Amazon Kindle later this summer</strong>.</li>
<li><a href="/printed-books/accessible-ux-research/" data-product-sku="accessible-ux-research" data-component="AddToCart" data-product-path="/printed-books/accessible-ux-research/" data-silent="true">Pre-order the book.</a></li>
</ul>
<h2 id="community-matters">Community Matters <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/2764.png" alt="❤" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h2>
<p>Producing a book takes quite a bit of time, and we couldn’t pull it off without the support of our wonderful <strong>community</strong>. A huge shout-out to Smashing Members for the kind, ongoing support. The eBook is and always will be <a href="https://www.smashingmagazine.com/membership">free for <em>Smashing Members</em> as soon as it’s out</a>. Plus, Members get a friendly discount when purchasing their printed copy. Just sayin’! <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<h2 id="more-smashing-books-amp-goodies">More Smashing Books &amp; Goodies</h2>
<p>Promoting best practices and providing you with practical tips to master your daily coding and design challenges has always been (and will be) at the <strong>core of everything we do</strong> at Smashing.</p>
<p>In the past few years, we were very lucky to have worked together with some talented, caring people from the web community to publish their wealth of experience as <a href="/printed-books/">printed books that stand the test of time</a>. Addy, Heather, and Steven are three of these people. Have you checked out their books already?</p>
<div class="book-grid break-out book-grid__in-post">
<figure class="book--featured">
<div class="book--featured__image"><a href="/printed-books/success-at-scale/"><img loading="lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Success at Scale" width="160" height="232" class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/06/success-at-scale-cover-release-opt.png"></a></div><figcaption>
<h4 class="book--featured__title"><a style="padding: 7px 0" href="/printed-books/success-at-scale/">Success at Scale</a></h4>
<p class="book--featured__desc">A deep dive into how production sites of different sizes tackle performance, accessibility, capabilities, and developer experience at scale.</p>
<p><a style="font-style: normal !important;color: #fff !important" class="btn btn--medium btn--green" href="/printed-books/success-at-scale/" data-product-path="/printed-books/success-at-scale/" data-product-sku="success-at-scale" data-component="AddToCart">Add to cart <span style="color:#fff;font-size:1em">$44</span></a></p>
</figcaption></figure>
<figure class="book--featured">
<div class="book--featured__image"><a href="/printed-books/understanding-privacy/"><img loading="lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Understanding Privacy" width="160" height="232" class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/06/understanding-privacy-cover-new-opt.png"></a></div><figcaption>
<h4 class="book--featured__title"><a href="/printed-books/understanding-privacy/" style="padding: 7px 0">Understanding Privacy</a></h4>
<p class="book--featured__desc">Everything you need to know to put your users first and make a better web.</p>
<p><a style="font-style: normal !important;color: #fff !important" class="btn btn--medium btn--green" href="/printed-books/understanding-privacy/" data-product-path="/printed-books/understanding-privacy/" data-product-sku="understanding-privacy" data-component="AddToCart">Add to cart <span style="color:#fff;font-size:1em">$44</span></a></p>
</figcaption></figure>
<figure class="book--featured">
<div class="book--featured__image"><a href="/printed-books/touch-design-for-mobile-interfaces/"><img loading="lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Touch Design for Mobile Interfaces" width="160" height="232" class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/06/touch-design-book-shop-opt.png"></a></div><figcaption>
<h4 class="book--featured__title"><a style="padding: 7px 0" href="/printed-books/touch-design-for-mobile-interfaces/">Touch Design for Mobile Interfaces</a></h4>
<p class="book--featured__desc">Learn how touchscreen devices really work &mdash; and how people really use them.</p>
<p><a style="font-style: normal !important;color: #fff !important" class="btn btn--medium btn--green" href="/printed-books/touch-design-for-mobile-interfaces/" data-product-path="/printed-books/touch-design-for-mobile-interfaces/" data-product-sku="touch-design-for-mobile-interfaces" data-component="AddToCart">Add to cart <span style="color:#fff;font-size:1em">$44</span></a></p>
</figcaption></figure>
</div>
<div class="signature">
  <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 />
  <span>(as, cm)</span>
</div>
</article>
]]></content:encoded>
					
					<wfw:commentRss>http://computercoursesonline.com/index.php/2025/06/18/meet-accessible-ux-research-a-brand-new-smashing-book/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Creating The &#8220;Moving Highlight&#8221; Navigation Bar With JavaScript And CSS</title>
		<link>http://computercoursesonline.com/index.php/2025/06/11/creating-the-moving-highlight-navigation-bar-with-javascript-and-css/</link>
					<comments>http://computercoursesonline.com/index.php/2025/06/11/creating-the-moving-highlight-navigation-bar-with-javascript-and-css/#respond</comments>
		
		<dc:creator><![CDATA[.]]></dc:creator>
		<pubDate>Wed, 11 Jun 2025 13:00:00 +0000</pubDate>
				<category><![CDATA[Javascript]]></category>
		<guid isPermaLink="false">http://computercoursesonline.com/?p=941</guid>

					<description><![CDATA[Creating The &#38;ldquo;Moving Highlight&#38;rdquo; Navigation Bar With JavaScript And CSS Creating The &#38;ldquo;Moving Highlight&#38;rdquo; Navigation Bar With JavaScript And CSS Blake Lundquist 2025-06-11T13:00:00+00:00 2025-06-12T20:33:08+00:00 I recently came across an old jQuery tutorial demonstrating a “moving highlight” navigation bar and decided the concept was due for a modern upgrade. With this pattern, the border around the...]]></description>
										<content:encoded><![CDATA[<p>              <title>Creating The &amp;ldquo;Moving Highlight&amp;rdquo; Navigation Bar With JavaScript And CSS</title></p>
<article>
<header>
<h1>Creating The &amp;ldquo;Moving Highlight&amp;rdquo; Navigation Bar With JavaScript And CSS</h1>
<address>Blake Lundquist</address>
<p>                  2025-06-11T13:00:00+00:00<br />
                  2025-06-12T20:33:08+00:00<br />
                </header>
<p>I recently came across an old jQuery tutorial demonstrating a <strong>“moving highlight” navigation bar</strong> and decided the concept was due for a modern upgrade. With this pattern, the border around the active navigation item animates directly from one element to another as the user clicks on menu items. In 2025, we have much better tools to manipulate the DOM via vanilla JavaScript. New features like the <a href="https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API">View Transition API</a> make progressive enhancement more easily achievable and handle a lot of the animation minutiae.</p>
<figure><a href="http://www.computercoursesonline.com/wp-content/uploads/2025/06/1-moving-highlight-navigation-bar.gif"><img loading="lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" width="800" height="131" alt="An example of a “moving highlight” navigation bar" class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/06/1-moving-highlight-navigation-bar.gif"></a><figcaption>(<a href="http://www.computercoursesonline.com/wp-content/uploads/2025/06/1-moving-highlight-navigation-bar.gif">Large preview</a>)</figcaption></figure>
<p>In this tutorial, I will demonstrate two methods of creating the “moving highlight” navigation bar using plain JavaScript and CSS. The first example uses the <code>getBoundingClientRect</code> method to explicitly animate the border between navigation bar items when they are clicked. The second example achieves the same functionality using the new View Transition API.</p>
<h2 id="the-initial-markup">The Initial Markup</h2>
<p>Let’s assume that we have a single-page application where content changes without the page being reloaded. The starting HTML and CSS are your standard navigation bar with an additional <code>div</code> element containing an <code>id</code> of <code>#highlight</code>. We give the first navigation item a class of <code>.active</code>.</p>
<figure class="break-out">
<p data-height="480" data-theme-id="light" data-slug-hash="EajQyBW" data-user="smashingmag" data-default-tab="result" class="codepen">See the Pen [Moving Highlight Navbar Starting Markup [forked]](https://codepen.io/smashingmag/pen/EajQyBW) by <a href="https://codepen.io/blakeeric">Blake Lundquist</a>.</p><figcaption>See the Pen <a href="https://codepen.io/smashingmag/pen/EajQyBW">Moving Highlight Navbar Starting Markup [forked]</a> by <a href="https://codepen.io/blakeeric">Blake Lundquist</a>.</figcaption></figure>
<p>For this version, we will position the <code>#highlight</code> element around the element with the <code>.active</code> class to create a border. We can utilize <code>absolute</code> positioning and animate the element across the navigation bar to create the desired effect. We’ll hide it off-screen initially by adding <code>left: -200px</code> and include <code>transition</code> styles for all properties so that any changes in the position and size of the element will happen gradually.</p>
<pre><code class="language-css">&#035;highlight {
  z-index: 0;
  position: absolute;
  height: 100%;
  width: 100px;
  left: -200px;
  border: 2px solid green;
  box-sizing: border-box;
  transition: all 0.2s ease;
}
</code></pre>
<div data-audience="non-subscriber" data-remove="true" class="feature-panel-container">
<aside class="feature-panel">
<div class="feature-panel-left-col">
<div class="feature-panel-description">
<p>Meet <strong><a data-instant href="/printed-books/touch-design-for-mobile-interfaces/">Touch Design for Mobile Interfaces</a></strong>, Steven Hoober’s brand-new guide on <strong>designing for mobile</strong> with proven, universal, human-centric guidelines. <strong>400 pages</strong>, jam-packed with in-depth user research and <strong>best practices</strong>.</p>
<p><a data-instant href="https://www.smashingmagazine.com/printed-books/touch-design-for-mobile-interfaces/" class="btn btn--green btn--large">Jump to table of contents&nbsp;↬</a></div>
</div>
<div class="feature-panel-right-col"><a data-instant href="https://www.smashingmagazine.com/printed-books/touch-design-for-mobile-interfaces/" class="feature-panel-image-link"></p>
<div class="feature-panel-image">
<img loading="lazy" class="feature-panel-image-img lazyload" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Feature Panel" width="480" height="697" data-src="https://archive.smashing.media/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/b14658fc-bb2d-41a6-8d1a-70eaaf1b8ec8/touch-design-book-shop-opt.png"></p>
</div>
<p></a>
</div>
</aside>
</div>
<h2 id="add-a-boilerplate-event-handler-for-click-interactions">Add A Boilerplate Event Handler For Click Interactions</h2>
<p>We want the highlight element to animate when a user changes the <code>.active</code> navigation item. Let’s add a <code>click</code> event handler to the <code>nav</code> element, then filter for events caused only by elements matching our desired selector. In this case, we only want to change the <code>.active</code> nav item if the user clicks on a link that does not already have the <code>.active</code> class.</p>
<p>Initially, we can call <code>console.log</code> to ensure the handler fires only when expected:</p>
<div class="break-out">
<pre><code class="language-javascript">const navbar = document.querySelector('nav');

navbar.addEventListener('click', function (event) {
  // return if the clicked element doesn't have the correct selector
  if (!event.target.matches('nav a:not(active)')) {
    return;
  }
  
  console.log('click');
});
</code></pre>
</div>
<p>Open your browser console and try clicking different items in the navigation bar. You should only see <code>&quot;click&quot;</code> being logged when you select a new item in the navigation bar.</p>
<p>Now that we know our event handler is working on the correct elements let’s add code to move the <code>.active</code> class to the navigation item that was clicked. We can use the object passed into the event handler to find the element that initialized the event and give that element a class of <code>.active</code> after removing it from the previously active item.</p>
<div class="break-out">
<pre><code class="language-javascript">const navbar = document.querySelector('nav');

navbar.addEventListener('click', function (event) {
  // return if the clicked element doesn't have the correct selector
  if (!event.target.matches('nav a:not(active)')) {
    return;
  }
  
-  console.log('click');
+  document.querySelector('nav a.active').classList.remove('active');
+  event.target.classList.add('active');
  
});
</code></pre>
</div>
<p>Our <code>#highlight</code> element needs to move across the navigation bar and position itself around the active item. Let’s write a function to calculate a new position and width. Since the <code>#highlight</code> selector has <code>transition</code> styles applied, it will move gradually when its position changes.</p>
<p>Using <code>getBoundingClientRect</code>, we can get information about the position and size of an element. We calculate the width of the active navigation item and its offset from the left boundary of the parent element. Then, we assign styles to the highlight element so that its size and position match.</p>
<div class="break-out">
<pre><code class="language-javascript">// handler for moving the highlight
const moveHighlight = () =&gt; {
  const activeNavItem = document.querySelector('a.active');
  const highlighterElement = document.querySelector('#highlight');
  
  const width = activeNavItem.offsetWidth;

  const itemPos = activeNavItem.getBoundingClientRect();
  const navbarPos = navbar.getBoundingClientRect()
  const relativePosX = itemPos.left - navbarPos.left;

  const styles = {
    left: `${relativePosX}px`,
    width: `${width}px`,
  };

  Object.assign(highlighterElement.style, styles);
}
</code></pre>
</div>
<p>Let’s call our new function when the click event fires:</p>
<div class="break-out">
<pre><code class="language-javascript">navbar.addEventListener('click', function (event) {
  // return if the clicked element doesn't have the correct selector
  if (!event.target.matches('nav a:not(active)')) {
    return;
  }
  
  document.querySelector('nav a.active').classList.remove('active');
  event.target.classList.add('active');
  
+  moveHighlight();
});
</code></pre>
</div>
<p>Finally, let’s also call the function immediately so that the border moves behind our initial active item when the page first loads:</p>
<pre><code class="language-javascript">// handler for moving the highlight
const moveHighlight = () =&gt; {
 // ...
}

// display the highlight when the page loads
moveHighlight();
</code></pre>
<p>Now, the border moves across the navigation bar when a new item is selected. Try clicking the different navigation links to animate the navigation bar.</p>
<figure class="break-out">
<p data-height="480" data-theme-id="light" data-slug-hash="WbvMxqV" data-user="smashingmag" data-default-tab="result" class="codepen">See the Pen [Moving Highlight Navbar [forked]](https://codepen.io/smashingmag/pen/WbvMxqV) by <a href="https://codepen.io/blakeeric">Blake Lundquist</a>.</p><figcaption>See the Pen <a href="https://codepen.io/smashingmag/pen/WbvMxqV">Moving Highlight Navbar [forked]</a> by <a href="https://codepen.io/blakeeric">Blake Lundquist</a>.</figcaption></figure>
<p>That only took a few lines of vanilla JavaScript and could easily be extended to account for other interactions, like <code>mouseover</code> events. In the next section, we will explore refactoring this feature using the View Transition API.</p>
<div class="partners__lead-place"></div>
<h2 id="using-the-view-transition-api">Using The View Transition API</h2>
<p>The View Transition API provides functionality to create animated transitions between website views. Under the hood, the API creates snapshots of “before” and “after” views and then handles transitioning between them. View transitions are useful for creating animations between documents, providing the <strong>native-app-like user experience</strong> featured in frameworks like <a href="https://docs.astro.build/en/guides/view-transitions/">Astro</a>. However, the API also provides handlers meant for <strong>SPA-style applications</strong>. We will use it to reduce the JavaScript needed in our implementation and more easily create fallback functionality.</p>
<p>For this approach, we no longer need a separate <code>#highlight</code> element. Instead, we can style the <code>.active</code> navigation item directly using pseudo-selectors and let the View Transition API handle the animation between the before-and-after UI states when a new navigation item is clicked.</p>
<p>We’ll start by getting rid of the <code>#highlight</code> element and its associated CSS and replacing it with styles for the <code>nav a::after</code> pseudo-selector:</p>
<pre><code class="language-html">&lt;nav&gt;
  - &lt;div id="highlight"&gt;&lt;/div&gt;
  &lt;a href="#" class="active"&gt;Home&lt;/a&gt;
  &lt;a href="#services"&gt;Services&lt;/a&gt;
  &lt;a href="#about"&gt;About&lt;/a&gt;
  &lt;a href="#contact"&gt;Contact&lt;/a&gt;
&lt;/nav&gt;
</code></pre>
<pre><code class="language-css">- &#035;highlight {
-  z-index: 0;
-  position: absolute;
-  height: 100%;
-  width: 0;
-  left: 0;
-  box-sizing: border-box;
-  transition: all 0.2s ease;
- }

+ nav a::after {
+  content: " ";
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  border: none;
+  box-sizing: border-box;
+ }
</code></pre>
<p>For the <code>.active</code> class, we include the <code>view-transition-name</code> property, thus unlocking the magic of the View Transition API. Once we trigger the view transition and change the location of the <code>.active</code> navigation item in the DOM, “before” and “after” snapshots will be taken, and the browser will animate the border across the bar. We’ll give our view transition the name of <code>highlight</code>, but we could theoretically give it any name.</p>
<pre><code class="language-css">nav a.active::after {
  border: 2px solid green;
  view-transition-name: highlight;
}
</code></pre>
<p>Once we have a selector that contains a <code>view-transition-name</code> property, the only remaining step is to trigger the transition using the <code>startViewTransition</code> method and pass in a callback function.</p>
<div class="break-out">
<pre><code class="language-javascript">const navbar = document.querySelector('nav');

// Change the active nav item on click
navbar.addEventListener('click', async  function (event) {

  if (!event.target.matches('nav a:not(.active)')) {
    return;
  }
  
  document.startViewTransition(() =&gt; {
    document.querySelector('nav a.active').classList.remove('active');

    event.target.classList.add('active');
  });
});
</code></pre>
</div>
<p>Above is a revised version of the <code>click</code> handler. Instead of doing all the calculations for the size and position of the moving border ourselves, the View Transition API handles all of it for us. We only need to call <code>document.startViewTransition</code> and pass in a callback function to change the item that has the <code>.active</code> class!</p>
<div class="partners__lead-place"></div>
<h2 id="adjusting-the-view-transition">Adjusting The View Transition</h2>
<p>At this point, when clicking on a navigation link, you’ll notice that the transition works, but some strange sizing issues are visible.</p>
<figure><a href="https://files.smashing.media/articles/creating-moving-highlight-navigation-bar-vanilla-javascript/2-view-transition-sizing-issues.gif"><img loading="lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" width="800" height="163" alt="The view transition with sizing issues" class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/06/2-view-transition-sizing-issues-800px.gif"></a><figcaption>(<a href="https://files.smashing.media/articles/creating-moving-highlight-navigation-bar-vanilla-javascript/2-view-transition-sizing-issues.gif">Large preview</a>)</figcaption></figure>
<p>This sizing inconsistency is caused by aspect ratio changes during the course of the view transition. We won’t go into detail here, but <a href="https://jakearchibald.com/2024/view-transitions-handling-aspect-ratio-changes/">Jake Archibald has a detailed explanation you can read</a> for more information. In short, to ensure the height of the border stays uniform throughout the transition, we need to declare an explicit <code>height</code> for the <code>::view-transition-old</code> and <code>::view-transition-new</code> pseudo-selectors representing a static snapshot of the old and new view, respectively.</p>
<pre><code class="language-css">::view-transition-old(highlight) {
  height: 100%;
}

::view-transition-new(highlight) {
  height: 100%;
}
</code></pre>
<p>Let’s do some final refactoring to tidy up our code by moving the callback to a separate function and adding a fallback for when view transitions aren’t supported:</p>
<div class="break-out">
<pre><code class="language-javascript">const navbar = document.querySelector('nav');

// change the item that has the .active class applied
const setActiveElement = (elem) =&gt; {
  document.querySelector('nav a.active').classList.remove('active');
  elem.classList.add('active');
}

// Start view transition and pass in a callback on click
navbar.addEventListener('click', async  function (event) {
  if (!event.target.matches('nav a:not(.active)')) {
    return;
  }

  // Fallback for browsers that don't support View Transitions:
  if (!document.startViewTransition) {
    setActiveElement(event.target);
    return;
  }
  
  document.startViewTransition(() =&gt; setActiveElement(event.target));
});
</code></pre>
</div>
<p>Here’s our view transition-powered navigation bar! Observe the smooth transition when you click on the different links.</p>
<figure class="break-out">
<p data-height="480" data-theme-id="light" data-slug-hash="ogXELKE" data-user="smashingmag" data-default-tab="result" class="codepen">See the Pen [Moving Highlight Navbar with View Transition [forked]](https://codepen.io/smashingmag/pen/ogXELKE) by <a href="https://codepen.io/blakeeric">Blake Lundquist</a>.</p><figcaption>See the Pen <a href="https://codepen.io/smashingmag/pen/ogXELKE">Moving Highlight Navbar with View Transition [forked]</a> by <a href="https://codepen.io/blakeeric">Blake Lundquist</a>.</figcaption></figure>
<h2 id="conclusion">Conclusion</h2>
<p>Animations and transitions between website UI states used to require many kilobytes of external libraries, along with verbose, confusing, and error-prone code, but vanilla JavaScript and CSS have since incorporated features to achieve <strong>native-app-like interactions without breaking the bank</strong>. We demonstrated this by implementing the “moving highlight” navigation pattern using two approaches: CSS transitions combined with the <code>getBoundingClientRect()</code> method and the View Transition API.</p>
<h3 id="resources">Resources</h3>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect"><code>getBoundingClientRect()</code> method documentation</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API">View Transition API documentation</a></li>
<li>“<a href="https://jakearchibald.com/2024/view-transitions-handling-aspect-ratio-changes/">View Transitions: Handling Aspect Ratio Changes</a>” by Jake Archibald</li>
</ul>
<div class="signature">
  <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 />
  <span>(gg, yk)</span>
</div>
</article>
]]></content:encoded>
					
					<wfw:commentRss>http://computercoursesonline.com/index.php/2025/06/11/creating-the-moving-highlight-navigation-bar-with-javascript-and-css/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Collaboration: The Most Underrated UX Skill No One Talks About</title>
		<link>http://computercoursesonline.com/index.php/2025/06/05/collaboration-the-most-underrated-ux-skill-no-one-talks-about/</link>
					<comments>http://computercoursesonline.com/index.php/2025/06/05/collaboration-the-most-underrated-ux-skill-no-one-talks-about/#respond</comments>
		
		<dc:creator><![CDATA[.]]></dc:creator>
		<pubDate>Thu, 05 Jun 2025 08:00:00 +0000</pubDate>
				<category><![CDATA[Ux]]></category>
		<guid isPermaLink="false">http://computercoursesonline.com/?p=937</guid>

					<description><![CDATA[Collaboration: The Most Underrated UX Skill No One Talks About Collaboration: The Most Underrated UX Skill No One Talks About Carrie Webster 2025-06-05T08:00:00+00:00 2025-06-05T21:02:28+00:00 When people talk about UX, it’s usually about the things they can see and interact with, like wireframes and prototypes, smart interactions, and design tools like Figma, Miro, or Maze. Some...]]></description>
										<content:encoded><![CDATA[<p>              <title>Collaboration: The Most Underrated UX Skill No One Talks About</title></p>
<article>
<header>
<h1>Collaboration: The Most Underrated UX Skill No One Talks About</h1>
<address>Carrie Webster</address>
<p>                  2025-06-05T08:00:00+00:00<br />
                  2025-06-05T21:02:28+00:00<br />
                </header>
<p>When people talk about UX, it’s usually about the things they can see and interact with, like wireframes and prototypes, smart interactions, and design tools like Figma, Miro, or Maze. Some of the outputs are even glamorized, like design systems, research reports, and pixel-perfect UI designs. But here’s the truth I’ve seen again and again in over two decades of working in UX: none of that moves the needle if there is no collaboration.</p>
<p><strong>Great UX doesn’t happen in isolation.</strong> It happens through conversations with engineers, product managers, customer-facing teams, and the customer support teams who manage support tickets. Amazing UX ideas come alive in messy Miro sessions, cross-functional workshops, and those online chats (e.g., Slack or Teams) where people align, adapt, and co-create.</p>
<p>Some of the most impactful moments in my career weren’t when I was “designing” in the traditional sense. They have been gaining incredible insights when discussing problems with teammates who have varied experiences, brainstorming, and coming up with ideas that I never could have come up with on my own. As I always say, ten minds in a room will come up with ten times as many ideas as one mind. Often, many ideas are the most useful outcome.</p>
<p>There have been times when a team has helped to reframe a problem in a workshop, taken vague and conflicting feedback, and clarified a path forward, or I’ve sat with a sales rep and heard the same user complaint show up in multiple conversations. This is when <strong>design becomes a team sport</strong>, and when your ability to capture the outcomes multiplies the UX impact.</p>
<div data-audience="non-subscriber" data-remove="true" class="feature-panel-container">
<aside class="feature-panel">
<div class="feature-panel-left-col">
<div class="feature-panel-description">
<p>Meet <strong><a data-instant href="https://www.smashingconf.com/online-workshops/">Smashing Workshops</a></strong> on <strong>front-end, design &amp; UX</strong>, with practical takeaways, live sessions, <strong>video recordings</strong> and a friendly Q&amp;A. With Brad Frost, Stéph Walter and <a href="https://smashingconf.com/online-workshops/workshops">so many others</a>.</p>
<p><a data-instant href="smashing-workshops" class="btn btn--green btn--large">Jump to the workshops&nbsp;↬</a></div>
</div>
<div class="feature-panel-right-col"><a data-instant href="smashing-workshops" class="feature-panel-image-link"></p>
<div class="feature-panel-image">
<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>
</div>
<p></a>
</div>
</aside>
</div>
<h2 id="why-this-article-matters-now">Why This Article Matters Now</h2>
<p>The reason collaboration feels so urgent now is that the way we work since COVID has changed, according to a <a href="https://www.bls.gov/opub/btn/volume-13/remote-work-productivity.htm">study published by the US Department of Labor</a>. Teams are more cross-functional, often remote, and increasingly complex. Silos are easier to fall into, due to distance or lack of face-to-face contact, and yet alignment has never been more important. We can’t afford to see collaboration as a “nice to have” anymore. It’s a <strong>core skill</strong>, especially in UX, where our work touches so many parts of an organisation.</p>
<p>Let’s break down what collaboration in UX really means, and why it deserves way more attention than it gets.</p>
<h2 id="what-is-collaboration-in-ux-really">What Is Collaboration In UX, Really?</h2>
<p>Let’s start by clearing up a misconception. Collaboration is not the same as cooperation.</p>
<ul>
<li><strong>Cooperation</strong>: “You do your thing, I’ll do mine, and we’ll check in later.”</li>
<li><strong>Collaboration</strong>: “Let’s figure this out together and co-own the outcome.”</li>
</ul>
<p>Collaboration, as defined in the <a href="https://oercollective.caul.edu.au/communication-concepts/chapter/defining-collaboration/">book Communication Concepts</a>, published by Deakin University, involves <strong>working with others to produce outputs</strong> and/or achieve shared goals. The outcome of collaboration is typically a tangible product or a measurable achievement, such as solving a problem or making a decision. Here’s an example from a recent project:</p>
<p>Recently, I worked on a fraud alert platform for a fintech business. It was a six-month project, and we had zero access to users, as the product had not yet hit the market. Also, the users were highly specialised in the B2B finance space and were difficult to find. Additionally, the team members I needed to collaborate with were based in Malaysia and Melbourne, while I am located in Sydney.</p>
<p>Instead of treating that as a dead end, we turned inward: collaborating with subject matter experts, professional services consultants, compliance specialists, and customer support team members who had deep knowledge of fraud patterns and customer pain points. Through bi-weekly workshops using a Miro board, iterative feedback loops, and sketching sessions, we worked on <strong>design solution options</strong>. I even asked them to present their own design version as part of the process.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/collaboration-most-underrated-ux-skill/1-miro-board.png"></p>
<p>    <img loading="lazy" width="800" height="364" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="A Miro board with design solutions" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/collaboration-most-underrated-ux-skill/1-miro-board.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      This Miro board shows a series of design solutions created by team members as part of a design thinking workshop. It was conducted online. (<a href="https://files.smashing.media/articles/collaboration-most-underrated-ux-skill/1-miro-board.png">Large preview</a>)<br />
    </figcaption></figure>
<p>After months of iterating on the fraud investigation platform through these collaboration sessions, I ended up with two different design frameworks for the investigator’s dashboard. Instead of just presenting the “best one” and hoping for buy-in, I ran a voting exercise with PMs, engineers, SMEs, and customer support. Everyone had a voice. The winning design was created and validated with the input of the team, resulting in an outcome that solved many problems for the end user and was <strong>owned by the entire team</strong>. That’s collaboration!</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/collaboration-most-underrated-ux-skill/2-miro-board-design-collaboration-workshops.png"></p>
<p>    <img loading="lazy" width="800" height="421" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Miro board with design collaboration workshops" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/collaboration-most-underrated-ux-skill/2-miro-board-design-collaboration-workshops.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      Multiple and ongoing design collaboration workshops as captured in this Miro board. Stakeholders could also return and comment at their convenience. (<a href="https://files.smashing.media/articles/collaboration-most-underrated-ux-skill/2-miro-board-design-collaboration-workshops.png">Large preview</a>)<br />
    </figcaption></figure>
<p>It is definitely one of the most satisfying projects of my career.</p>
<p>On the other hand, I recently caught up with an old colleague who now serves as a product owner. Her story was a cautionary tale: the design team had gone ahead with a major redesign of an app without looping her in until late in the game. Not surprisingly, the new design missed several key product constraints and business goals. It had to be scrapped and redone, with her now at the table. That experience reinforced what we all know deep down: your best work rarely happens in isolation.</p>
<p>As illustrated in my experience, <strong>true collaboration can span many roles</strong>. It’s not just between designers and PMs. It can also include QA testers who identify real-world issues, content strategists who ensure our language is clear and inclusive, sales representatives who interact with customers on a daily basis, marketers who understand the brand’s voice, and, of course, customer support agents who are often the first to hear when something goes wrong. The best outcomes arrive when we’re open to <strong>different perspectives and inputs</strong>.</p>
<h2 id="why-collaboration-is-so-overlooked">Why Collaboration Is So Overlooked?</h2>
<p>If collaboration is so powerful, why don’t we talk about it more?</p>
<p>In my experience, one reason is the <a href="https://socialinnovationsjournal.org/editions/75-disruptive-innovations/2908-let-s-bust-the-lone-hero-myth-the-role-of-collective-leadership-in-systems-change#:~:text=It%20requires%20an%20understanding%20of,affected%20by%20the%20targeted%20issue.">myth of the “lone UX hero”</a>.  Many of us entered the field inspired by stories of design geniuses revolutionising products on their own. Our portfolios often reflect that as well. We showcase our solo work, our processes, and our wins. Job descriptions often reinforce the idea of the solo UX designer, listing tool proficiency and deliverables more than soft skills and team dynamics.</p>
<p>And then there’s the team culture within many organisations of “just get the work done”, which often leads to fewer meetings and tighter deadlines. As a result, a sense of collaboration is inefficient and wasted. I have also experienced working with some designers where perfectionism and territoriality creep in &mdash; “This is my design” &mdash; which kills the open, communal spirit that collaboration needs.</p>
<div class="partners__lead-place"></div>
<h2 id="when-collaboration-is-the-user-research">When Collaboration Is The User Research</h2>
<p>In an ideal world, we’d always have direct access to users. But let’s be real. Sometimes that just doesn’t happen. Whether it’s due to budget constraints, time limitations, or layers of bureaucracy, talking to end users isn’t always possible. That’s where collaboration with team members becomes even more crucial.</p>
<p>The next best thing to talking to users? Talking to the people who talk to users. Sales teams, customer success reps, tech support, and field engineers. They’re all user researchers in disguise!</p>
<p>On another B2C project, the end users were having trouble completing the key task. My role was to redesign the onboarding experience for an online identity capture tool for end users. I was unable to schedule interviews with end users due to budget and time constraints, so I turned to the sales and tech support teams.</p>
<p>I conducted multiple mini-workshops to identify the most common onboarding issues they had heard directly from our customers. This led to a huge “aha” moment: most users dropped off before the document capture process. They may have been struggling with a lack of instruction, not knowing the required time, or not understanding the steps involved in completing the onboarding process.</p>
<p>That insight reframed my approach, and we ultimately redesigned the flow to prioritize orientation and clear instructions before proceeding to the setup steps. Below is an example of one of the screen designs, including some of the instructions we added.</p>
<figure class="
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/collaboration-most-underrated-ux-skill/3-screen-design.png"></p>
<p>    <img loading="lazy" width="800" height="885" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="A screen design" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/collaboration-most-underrated-ux-skill/3-screen-design.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      The screen design above includes some of the instructions we added after our design workshop outcomes. (<a href="https://files.smashing.media/articles/collaboration-most-underrated-ux-skill/3-screen-design.png">Large preview</a>)<br />
    </figcaption></figure>
<p>This kind of collaboration <em>is</em> user research. It’s not a substitute for talking to users directly, but it’s a <strong>powerful proxy</strong> when you have limited options.</p>
<h2 id="but-what-about-using-ai">But What About Using AI?</h2>
<p>Glad you asked! Even AI tools, which are increasingly being used for idea generation, pattern recognition, or rapid prototyping, don’t replace collaboration; they just change the shape of it.</p>
<p>AI can help you explore design patterns, draft user flows, or generate multiple variations of a layout in seconds. It’s fantastic for getting past creative blocks or pressure-testing your assumptions. But let’s be clear: these tools are accelerators, not oracles. As an innovation and strategy consultant <a href="https://www.linkedin.com/pulse/team-collaboration-does-ai-help-hinder-nathan-waterhouse-canse/">Nathan Waterhouse points out</a>, AI can point you in a direction, but it can’t tell you which direction is the <em>right</em> one in your specific context. That still requires human judgment, empathy, and an understanding of the messy realities of users and business goals.</p>
<p>You still need people, especially those closest to your users, to validate, challenge, and evolve any AI-generated idea. For instance, you might use ChatGPT to brainstorm onboarding flows for a SaaS tool, but if you’re not involving customer support reps who regularly hear <em>“I didn’t know where to start”</em> or <em>“I couldn’t even log in,”</em> you’re just working with assumptions. The same applies to engineers who know what is technically feasible or PMs who understand where the business is headed.</p>
<blockquote class="pull-quote">
<p>
    <a class="pull-quote__link" aria-label="Share on Twitter" href="https://twitter.com/share?text=%0aAI%20can%20generate%20ideas,%20but%20only%20collaboration%20turns%20those%20ideas%20into%20something%20usable,%20valuable,%20and%20real.%20Think%20of%20it%20as%20a%20powerful%20ingredient,%20but%20not%20the%20whole%20recipe.%0a&amp;url=https://smashingmagazine.com%2f2025%2f06%2fcollaboration-most-underrated-ux-skill%2f"></p>
<p>AI can generate ideas, but only collaboration turns those ideas into something usable, valuable, and real. Think of it as a powerful ingredient, but not the whole recipe.</p>
<p>    </a>
  </p>
<div class="pull-quote__quotation">
<div class="pull-quote__bg">
      <span class="pull-quote__symbol">“</span></div>
</p></div>
</blockquote>
<h2 id="how-to-strengthen-your-ux-collaboration-skills">How To Strengthen Your UX Collaboration Skills?</h2>
<p>If collaboration doesn’t come naturally or hasn’t been a focus, that’s okay. Like any skill, it can be practiced and improved. Here are a few ways to level up:</p>
<ol>
<li><strong>Cultivate curiosity about your teammates.</strong><br />
Ask engineers what keeps them up at night. Learn what metrics your PMs care about. Understand the types of tickets the support team handles most frequently. The more you care about their challenges, the more they&rsquo;ll care about yours.</li>
<li><strong>Get comfortable facilitating.</strong><br />
You don’t need to be a certified Design Sprint master, but learning how to run a structured conversation, align stakeholders, or synthesize different points of view is hugely valuable. Even a simple “What’s working? What’s not?” retro can be an amazing starting point in identifying where you need to focus next.</li>
<li><strong>Share early, share often.</strong><br />
Don’t wait until your designs are polished to get input. Messy sketches and rough prototypes invite collaboration. When others feel like they’ve helped shape the work, they’re more invested in its success.</li>
<li><strong>Practice active listening.</strong><br />
When someone critiques your work, don’t immediately defend. Pause. Ask follow-up questions. Reframe the feedback. Collaboration isn’t about consensus; it’s about finding a shared direction that can honour multiple truths.</li>
<li><strong>Co-own the outcome.</strong><br />
Let go of your ego. The best UX work isn’t “your” work. It’s the result of many voices, skill sets, and conversations converging toward a solution that helps users. It’s not “I”, it’s “we” that will solve this problem together.</li>
</ol>
<div class="partners__lead-place"></div>
<h2 id="conclusion-ux-is-a-team-sport">Conclusion: UX Is A Team Sport</h2>
<p>Great design doesn’t emerge from a vacuum. It comes from <strong>open dialogue</strong>, <strong>cross-functional understanding</strong>, and a <strong>shared commitment</strong> to solving real problems for real people.</p>
<p>If there’s one thing I wish every early-career designer knew, it’s this:</p>
<blockquote class="pull-quote">
<p>
    <a class="pull-quote__link" aria-label="Share on Twitter" href="https://twitter.com/share?text=%0aCollaboration%20is%20not%20a%20side%20skill.%20It%e2%80%99s%20the%20engine%20behind%20every%20meaningful%20design%20outcome.%20And%20for%20seasoned%20professionals,%20it%e2%80%99s%20the%20superpower%20that%20turns%20good%20teams%20into%20great%20ones.%0a&amp;url=https://smashingmagazine.com%2f2025%2f06%2fcollaboration-most-underrated-ux-skill%2f"></p>
<p>Collaboration is not a side skill. It’s the engine behind every meaningful design outcome. And for seasoned professionals, it’s the superpower that turns good teams into great ones.</p>
<p>    </a>
  </p>
<div class="pull-quote__quotation">
<div class="pull-quote__bg">
      <span class="pull-quote__symbol">“</span></div>
</p></div>
</blockquote>
<p>So next time you’re tempted to go heads-down and just “crank out a design,” pause to reflect. Ask who else should be in the room. And invite them in, not just to review your work, but to help create it.</p>
<p>Because in the end, the best UX isn’t just what you make. It’s what you make <em>together</em>.</p>
<h3 id="further-reading-on-smashingmag">Further Reading On SmashingMag</h3>
<ul>
<li>“<a href="https://www.smashingmagazine.com/2024/06/presenting-ux-research-design-stakeholders/">Presenting UX Research And Design To Stakeholders: The Power Of Persuasion</a>,” Victor Yocco</li>
<li>“<a href="https://www.smashingmagazine.com/2024/05/transforming-relationship-between-designers-developers/">Transforming The Relationship Between Designers And Developers</a>,” Chris Day</li>
<li>“<a href="https://www.smashingmagazine.com/2022/10/effective-communication-everyday-meetings/">Effective Communication For Everyday Meetings</a>,” Andrii Zhdan</li>
<li>“<a href="https://www.smashingmagazine.com/2022/04/ux-integrated-design-workflows/">Preventing Bad UX Through Integrated Design Workflows</a>,” Ceara Crawshaw</li>
</ul>
<div class="signature">
  <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 />
  <span>(yk)</span>
</div>
</article>
]]></content:encoded>
					
					<wfw:commentRss>http://computercoursesonline.com/index.php/2025/06/05/collaboration-the-most-underrated-ux-skill-no-one-talks-about/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Smashing Animations Part 4: Optimising SVGs</title>
		<link>http://computercoursesonline.com/index.php/2025/06/04/smashing-animations-part-4-optimising-svgs/</link>
					<comments>http://computercoursesonline.com/index.php/2025/06/04/smashing-animations-part-4-optimising-svgs/#respond</comments>
		
		<dc:creator><![CDATA[.]]></dc:creator>
		<pubDate>Wed, 04 Jun 2025 08:00:00 +0000</pubDate>
				<category><![CDATA[Css]]></category>
		<guid isPermaLink="false">http://computercoursesonline.com/?p=933</guid>

					<description><![CDATA[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...]]></description>
										<content:encoded><![CDATA[<p>              <title>Smashing Animations Part 4: Optimising SVGs</title></p>
<article>
<header>
<h1>Smashing Animations Part 4: Optimising SVGs</h1>
<address>Andy Clarke</address>
<p>                  2025-06-04T08:00:00+00:00<br />
                  2025-06-05T21:02:28+00:00<br />
                </header>
<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>
<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’s how I do it.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://stuffandnonsense.co.uk/toon-titles"></p>
<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>
<p>    </a><figcaption class="op-vertical-bottom">
      There’s 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 />
    </figcaption></figure>
<div class="refs">
<ul>
<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>
<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>
<li><a href="https://www.smashingmagazine.com/2025/05/smashing-animations-part-3-smil-not-dead/">Smashing Animations Part 3: SMIL’s Not Dead Baby, SMIL’s Not Dead</a></li>
</ul>
</div>
<p>Whether for personal projects or commercial work, preparing SVGs well ensures they’re accessible. Optimising them ensures they load quickly, especially on mobile, and thinking carefully about how they’re structured makes maintaining them easier. I’ve developed a <strong>process that balances visuals with accessibility and performance</strong> and makes complex SVGs easier to work with.</p>
<p>So, to explain my process, I’ve chosen an episode of <em>The Yogi Bear Show</em> called “Bewitched Bear,” first broadcast in January 1960. In this story, Yogi steals a witch’s broom to help him grab “pic-a-nic” baskets.</p>
<p>“Hey, hey, hey!”</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/2-yogi-bear-bewitched-bear.png"></p>
<p>    <img loading="lazy" width="800" height="540" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="An illustration from the “Bewitched Bear” episode of The Yogi Bear Show where bear is on a witch’s 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>
<p>    </a><figcaption class="op-vertical-bottom">
      The Yogi Bear Show © 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 />
    </figcaption></figure>
<div data-audience="non-subscriber" data-remove="true" class="feature-panel-container">
<aside class="feature-panel">
<div class="feature-panel-left-col">
<div class="feature-panel-description">
<p>Meet <strong><a data-instant href="https://www.smashingconf.com/online-workshops/">Smashing Workshops</a></strong> on <strong>front-end, design &amp; UX</strong>, with practical takeaways, live sessions, <strong>video recordings</strong> and a friendly Q&amp;A. With Brad Frost, Stéph Walter and <a href="https://smashingconf.com/online-workshops/workshops">so many others</a>.</p>
<p><a data-instant href="smashing-workshops" class="btn btn--green btn--large">Jump to the workshops&nbsp;↬</a></div>
</div>
<div class="feature-panel-right-col"><a data-instant href="smashing-workshops" class="feature-panel-image-link"></p>
<div class="feature-panel-image">
<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>
</div>
<p></a>
</div>
</aside>
</div>
<h2 id="start-clean-and-design-with-optimisation-in-mind">Start Clean And Design With Optimisation In Mind</h2>
<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>
<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>
<h2 id="beginning-with-outlines">Beginning With Outlines</h2>
<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>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/3-outlines-anchor-points.png"></p>
<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>
<p>    </a><figcaption class="op-vertical-bottom">
      <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 />
    </figcaption></figure>
<p>Bearing in mind that parts of this Yogi illustration will ultimately be animated, I keep outlines for this Bewitched Bear’s 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’s collar will hide the joins between them.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/4-separate-outlines.png"></p>
<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>
<p>    </a><figcaption class="op-vertical-bottom">
      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 />
    </figcaption></figure>
<h2 id="drawing-simple-background-shapes">Drawing Simple Background Shapes</h2>
<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’t need to match them exactly. The fewer anchor points, the smaller the file size.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/5-simple-background-shapes.png"></p>
<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>
<p>    </a><figcaption class="op-vertical-bottom">
      <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 />
    </figcaption></figure>
<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>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/6-adobe-illustrator-simplify-paths.png"></p>
<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>
<p>    </a><figcaption class="op-vertical-bottom">
      Adobe Illustrator: Object → Path → Simplify. (<a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/6-adobe-illustrator-simplify-paths.png">Large preview</a>)<br />
    </figcaption></figure>
<h2 id="optimising-the-code">Optimising The Code</h2>
<p>It’s not just metadata that makes SVG bulkier. The way you export from your design app also affects file size.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/7-vector-artwork-ready-optimisation.png"></p>
<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>
<p>    </a><figcaption class="op-vertical-bottom">
      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 />
    </figcaption></figure>
<p>Exporting just those simple background shapes from Adobe Illustrator includes unnecessary groups, masks, and bloated path data by default. Sketch’s code is barely any better, and there’s plenty of room for improvement, even in its SVGO Compressor code. I rely on Jake Archibald’s <a href="https://jakearchibald.github.io/svgomg/">SVGOMG</a>, which uses SVGO v3 and consistently delivers the best optimised SVGs.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/8-jake-archibald-svgomg-online-optimisation-tool.png"></p>
<p>    <img loading="lazy" width="800" height="439" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Jake Archibald’s 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>
<p>    </a><figcaption class="op-vertical-bottom">
      Jake Archibald’s 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 />
    </figcaption></figure>
<div class="partners__lead-place"></div>
<h2 id="layering-svg-elements">Layering SVG Elements</h2>
<p>My process for preparing SVGs for animation goes well beyond drawing vectors and optimising paths &mdash; 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>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/9-yogi-bear-title-card-toon-titles-recreation.png"></p>
<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>
<p>    </a><figcaption class="op-vertical-bottom">
      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 />
    </figcaption></figure>
<p>That’s why I develop my SVGs in layers, exporting and optimising one set of elements at a time &mdash; always in the order they’ll 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>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/10-gradient-background-title-graphic.png"></p>
<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>
<p>    </a><figcaption class="op-vertical-bottom">
      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 />
    </figcaption></figure>
<p>Instead of facing a wall of SVG code, I can now easily identify the background gradient’s 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>
<pre><code class="language-svg">&lt;svg ...&gt;
  &lt;defs&gt;
    &lt;!-- ... --&gt;
  &lt;/defs&gt;
  &lt;path fill="url(#grad)" d="…"/&gt;
  &lt;!-- TITLE GRAPHIC --&gt;
  &lt;g&gt;
    &lt;path … /&gt;
    &lt;!-- ... --&gt; 
  &lt;/g&gt;
&lt;/svg&gt;
</code></pre>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/11-trail-gaussian-blur.png"></p>
<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>
<p>    </a><figcaption class="op-vertical-bottom">
      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 />
    </figcaption></figure>
<p>Next, I add the blurred trail from Yogi’s airborne broom. This includes defining a Gaussian Blur filter and placing its path between the background and title layers:</p>
<pre><code class="language-svg">&lt;svg ...&gt;
  &lt;defs&gt;
    &lt;linearGradient id="grad" …&gt;…&lt;/linearGradient&gt;
    &lt;filter id="trail" …&gt;…&lt;/filter&gt;
  &lt;/defs&gt;
  &lt;!-- GRADIENT --&gt;
  &lt;!-- TRAIL --&gt;
  &lt;path filter="url(#trail)" …/&gt;
  &lt;!-- TITLE GRAPHIC --&gt;
&lt;/svg&gt;
</code></pre>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/12-yogi-bear-magical-stars.png"></p>
<p>    <img loading="lazy" width="800" height="450" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Yogi Bear’s 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>
<p>    </a><figcaption class="op-vertical-bottom">
      Yogi Bear’s 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 />
    </figcaption></figure>
<p>Then come the magical stars, added in the same sequential fashion:</p>
<pre><code class="language-svg">&lt;svg ...&gt;
  &lt;!-- GRADIENT --&gt;
  &lt;!-- TRAIL --&gt;
  &lt;!-- STARS --&gt;
  &lt;!-- TITLE GRAPHIC --&gt;
&lt;/svg&gt;
</code></pre>
<p>To keep everything organised and animation-ready, I create an empty group that will hold all the parts of Yogi:</p>
<pre><code class="language-svg">&lt;g id="yogi"&gt;...&lt;/g&gt;
</code></pre>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/13-yogi-bear-component-parts.png"></p>
<p>    <img loading="lazy" width="800" height="450" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Added Yogi Bear’s 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>
<p>    </a><figcaption class="op-vertical-bottom">
      Sequentially adding Yogi Bear’s 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 />
    </figcaption></figure>
<p>Then I build Yogi from the ground up &mdash; starting with background props, like his broom:</p>
<pre><code class="language-svg">&lt;g id="broom"&gt;...&lt;/g&gt;
</code></pre>
<p>Followed by grouped elements for his body, head, collar, and tie:</p>
<pre><code class="language-svg">&lt;g id="yogi"&gt;
  &lt;g id="broom"&gt;…&lt;/g&gt;
  &lt;g id="body"&gt;…&lt;/g&gt;
  &lt;g id="head"&gt;…&lt;/g&gt;
  &lt;g id="collar"&gt;…&lt;/g&gt;
  &lt;g id="tie"&gt;…&lt;/g&gt;
&lt;/g&gt;
</code></pre>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/14-yogi-bear-title-card-toon-titles-recreation.png"></p>
<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>
<p>    </a><figcaption class="op-vertical-bottom">
      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 />
    </figcaption></figure>
<p>Since I export each layer from the same-sized artboard, I don’t need to worry about alignment or positioning issues later on &mdash; they’ll 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>
<h2 id="reusing-elements-with-use">Reusing Elements With <code>&lt;use&gt;</code></h2>
<p>When duplicate shapes get reused repeatedly, SVG files can get bulky fast. My recreation of the “Bewitched Bear” 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>
<pre><code class="language-svg">&lt;g id="stars"&gt;
 &lt;path class="star-small" fill="#eae3da" d="..."/&gt;
 &lt;path class="star-medium" fill="#eae3da" d="..."/&gt;
 &lt;path class="star-large" fill="#eae3da" d="..."/&gt;
 &lt;!-- ... --&gt;
&lt;/g&gt;
</code></pre>
<p>Moving the stars’ <code>fill</code> attribute values to their parent group reduces the overall weight a little:</p>
<pre><code class="language-svg">&lt;g id="stars" fill="#eae3da"&gt;
 &lt;path class="star-small" d="…"/&gt;
 &lt;path class="star-medium" d="…"/&gt;
 &lt;path class="star-large" d="…"/&gt;
 &lt;!-- ... --&gt;
&lt;/g&gt;
</code></pre>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/15-yogi-bear-sparkling-stars.png"></p>
<p>    <img loading="lazy" width="800" height="450" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Yogi Bear’s 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>
<p>    </a><figcaption class="op-vertical-bottom">
      Yogi Bear’s 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 />
    </figcaption></figure>
<p>But a more efficient and manageable option is to define each star size as a reusable template:</p>
<div class="break-out">
<pre><code class="language-svg">&lt;defs&gt;
  &lt;path id="star-large" fill="#eae3da" fill-rule="evenodd" d="…"/&gt;
  &lt;path id="star-medium" fill="#eae3da" fill-rule="evenodd" d="…"/&gt;
  &lt;path id="star-small" fill="#eae3da" fill-rule="evenodd" d="…"/&gt;
&lt;/defs&gt;
</code></pre>
</div>
<p>With this setup, changing a star’s design only means updating its template once, and every instance updates automatically. Then, I reference each one using <code>&lt;use&gt;</code> and position them with <code>x</code> and <code>y</code> attributes:</p>
<pre><code class="language-svg">&lt;g id="stars"&gt;
  &lt;!-- Large stars --&gt;
  &lt;use href="#star-large" x="1575" y="495"/&gt;
  &lt;!-- ... --&gt;
  &lt;!-- Medium stars --&gt;
  &lt;use href="#star-medium" x="1453" y="696"/&gt;
  &lt;!-- ... --&gt;
  &lt;!-- Small stars --&gt;
  &lt;use href="#star-small" x="1287" y="741"/&gt;
  &lt;!-- ... --&gt;
&lt;/g&gt;
</code></pre>
<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>
<div class="partners__lead-place"></div>
<h2 id="adding-animations">Adding Animations</h2>
<p>The stars trailing behind Yogi’s 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>
<pre><code class="language-css">@keyframes sparkle {
  0%, 100% { opacity: .1; }
  50% { opacity: 1; }
}
</code></pre>
<p>Next, I applied this looping animation to every <code>use</code> element inside my stars group:</p>
<pre><code class="language-css">&#035;stars use {
  animation: sparkle 10s ease-in-out infinite;
}
</code></pre>
<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>
<pre><code class="language-css">/&#042; Fast, frequent &#042;/
&#035;stars use:nth-child(n + 1):nth-child(-n + 10) {
  animation-delay: .1s;
  animation-duration: 2s;
}
</code></pre>
<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>
<pre><code class="language-css">/&#042; Medium &#042;/
&#035;stars use:nth-child(n + 11):nth-child(-n + 20) { ... }

/&#042; Slow, dramatic &#042;/
&#035;stars use:nth-child(n + 21):nth-child(-n + 30) { ... }

/&#042; Random &#042;/
&#035;stars use:nth-child(3n + 2) { ... }

/&#042; Alternating &#042;/
&#035;stars use:nth-child(4n + 1) { ... }

/&#042; Scattered &#042;/
&#035;stars use:nth-child(n + 31) { ... }
</code></pre>
<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>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-4-optimising-svgs/16-subtle-movements-yogi-bear.png"></p>
<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>
<p>    </a><figcaption class="op-vertical-bottom">
      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 />
    </figcaption></figure>
<p>Then, for added realism, I make Yogi’s head wobble:</p>
<div class="break-out">
<pre><code class="language-css">@keyframes headWobble {
  0% { transform: rotate(-0.8deg) translateY(-0.5px); }
  100% { transform: rotate(0.9deg) translateY(0.3px); }
}

&#035;head {
  animation: headWobble 0.8s cubic-bezier(0.5, 0.15, 0.5, 0.85) infinite alternate;
}
</code></pre>
</div>
<p>His tie waves:</p>
<div class="break-out">
<pre><code class="language-css">@keyframes tieWave {
  0%, 100% { transform: rotateZ(-4deg) rotateY(15deg) scaleX(0.96); }
  33% { transform: rotateZ(5deg) rotateY(-10deg) scaleX(1.05); }
  66% { transform: rotateZ(-2deg) rotateY(5deg) scaleX(0.98); }
}

&#035;tie {
  transform-style: preserve-3d;
  animation: tieWave 10s cubic-bezier(0.68, -0.55, 0.27, 1.55) infinite;
}
</code></pre>
</div>
<p>His broom swings:</p>
<div class="break-out">
<pre><code class="language-css">@keyframes broomSwing {
  0%, 20% { transform: rotate(-5deg); }
  30% { transform: rotate(-4deg); }
  50%, 70% { transform: rotate(5deg); }
  80% { transform: rotate(4deg); }
  100% { transform: rotate(-5deg); }
}

&#035;broom {
  animation: broomSwing 4s cubic-bezier(0.5, 0.05, 0.5, 0.95) infinite;
}
</code></pre>
</div>
<p>And, finally, Yogi himself gently rotates as he flies on his magical broom:</p>
<div class="break-out">
<pre><code class="language-css">@keyframes yogiWobble {
  0% { transform: rotate(-2.8deg) translateY(-0.8px) scale(0.998); }
  30% { transform: rotate(1.5deg) translateY(0.3px); }
  100% { transform: rotate(3.2deg) translateY(1.2px) scale(1.002); }
}

&#035;yogi {
  animation: yogiWobble 3.5s cubic-bezier(.37, .14, .3, .86) infinite alternate;
}
</code></pre>
</div>
<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>
<p>Try this yourself:</p>
<figure class="break-out">
<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>
<h2 id="conclusion">Conclusion</h2>
<p>Whether you’re recreating a classic title card or animating icons for an interface, the principles are the same:</p>
<ol>
<li>Start clean,</li>
<li>Optimise early, and</li>
<li>Structure everything with animation in mind.</li>
</ol>
<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 &mdash; layer by layer, element by element &mdash; you’ll spend less time untangling code and more time bringing your work to life.</p>
<div class="signature">
  <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 />
  <span>(gg, yk)</span>
</div>
</article>
]]></content:encoded>
					
					<wfw:commentRss>http://computercoursesonline.com/index.php/2025/06/04/smashing-animations-part-4-optimising-svgs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Designing For Neurodiversity</title>
		<link>http://computercoursesonline.com/index.php/2025/06/02/designing-for-neurodiversity/</link>
					<comments>http://computercoursesonline.com/index.php/2025/06/02/designing-for-neurodiversity/#respond</comments>
		
		<dc:creator><![CDATA[.]]></dc:creator>
		<pubDate>Mon, 02 Jun 2025 08:00:00 +0000</pubDate>
				<category><![CDATA[Ux]]></category>
		<guid isPermaLink="false">http://computercoursesonline.com/?p=939</guid>

					<description><![CDATA[Designing For Neurodiversity Designing For Neurodiversity Vitaly Friedman 2025-06-02T08:00:00+00:00 2025-06-05T21:02:28+00:00 This article is sponsored by TetraLogical Neurodivergent needs are often considered as an edge case that doesn’t fit into common user journeys or flows. Neurodiversity tends to get overlooked in the design process. Or it is tackled late in the process, and only if there...]]></description>
										<content:encoded><![CDATA[<p>              <title>Designing For Neurodiversity</title></p>
<article>
<header>
<h1>Designing For Neurodiversity</h1>
<address>Vitaly Friedman</address>
<p>                  2025-06-02T08:00:00+00:00<br />
                  2025-06-05T21:02:28+00:00<br />
                </header>
<p>This article is sponsored by <b>TetraLogical</b></p>
<p>Neurodivergent needs are often considered as an edge case that doesn’t fit into common user journeys or flows. Neurodiversity tends to get overlooked in the design process. Or it is tackled late in the process, and only if there is enough time.</p>
<p>But <strong>people aren’t edge cases</strong>. Every person is just a different person, performing tasks and navigating the web in a different way. So how can we design better, <strong>more inclusive experiences</strong> that cater to different needs and, ultimately, benefit everyone? Let’s take a closer look.</p>
<figure class="
  
  
  "></p>
<p>    <a href="https://neurodiversity.design/"></p>
<p>    <img loading="lazy" width="800" height="765" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Neurodiversity Design System" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/designing-for-neurodiversity/1-neurodiversity-practical-guides.jpeg"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      By considering neurodiversity early in the design process, we can create better experiences for everyone. (Image source: <a href="https://neurodiversity.design/">Neurodiversity Design System</a>) (<a href="https://files.smashing.media/articles/designing-for-neurodiversity/1-neurodiversity-practical-guides.jpeg">Large preview</a>)<br />
    </figcaption></figure>
<h2 id="neurodiversity-or-neurodivergent">Neurodiversity Or Neurodivergent?</h2>
<p>There is quite a bit of confusion about both terms on the web. Different people think and experience the world differently, and <strong>neurodiversity</strong> sees differences as natural variations, not deficits. It distinguishes between <strong>neurotypical</strong> and <strong>neurodivergent</strong> people.</p>
<ul>
<li><strong>Neurotypical</strong> people see the world in a “typical” and widely perceived as expected way.</li>
<li><strong>Neurodivergent</strong> people experience the world differently, for example, people with ADHD, dyslexia, dyscalculia, synesthesia, and hyperlexia.<br />
</li>
</ul>
<p>According to various sources, around <strong>15–40% of the population</strong> has neurodivergent traits. These traits can be innate (e.g., autism) or acquired (e.g., trauma). But they are always on a spectrum, and vary a lot. A person with <strong>autism is not neurodiverse</strong> &mdash; they are neurodivergent.</p>
<p>One of the main strengths of neurodivergent people is how <strong>imaginative and creative</strong> they are, coming up with out-of-the-box ideas quickly. With exceptional levels of attention, strong long-term memory, a unique perspective, unbeatable accuracy, and a strong sense of justice and fairness.</p>
<p>Being different in a world that, to some degree, still doesn’t accept these differences is exhausting. So unsurprisingly, neurodivergent people often bring along determination, resilience, and <strong>high levels of empathy</strong>.</p>
<h2 id="design-with-people-not-for-them">Design With People, Not For Them</h2>
<p>As a designer, I often see myself as a <strong>path-maker</strong>. I’m designing reliable paths for people to navigate to their goals comfortably. Without being blocked. Or confused. Or locked out.</p>
<p>That means respecting the simple fact that people’s needs, tasks, and user journeys are all different, and that they evolve over time. And: most importantly, it means considering them very <strong>early in the process</strong>.</p>
<p>Better accessibility is better for everyone. Instead of making decisions that need to be reverted or refined to be compliant, we can bring a <strong>diverse group of people</strong> &mdash; with accessibility needs, with neurodiversity, frequent and infrequent users, experts, newcomers &mdash; in the process, and design with them, rather than for them.</p>
<h2 id="neurodiversity-amp-inclusive-design-resources">Neurodiversity &amp; Inclusive Design Resources</h2>
<p>A wonderful resource that helps us design for cognitive accessibility is Stéphanie Walter’s <a href="https://stephaniewalter.design/blog/neurodiversity-and-ux-essential-resources-for-cognitive-accessibility/"><strong>Neurodiversity and UX toolkit</strong></a>. It includes <strong>practical guidelines</strong>, tools, and resources to better understand and design for dyslexia, dyscalculia, autism, and ADHD.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://stephaniewalter.design/blog/neurodiversity-and-ux-essential-resources-for-cognitive-accessibility"></p>
<p>    <img loading="lazy" width="800" height="744" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Neurodiversity and UX: Essential Resources for Cognitive Accessibility" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/designing-for-neurodiversity/2-neurodiversity-and-ux-essential-resources-for-cognitive-accessibility.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      <a href="https://accessibility.blog.gov.uk/2016/09/02/dos-and-donts-on-designing-for-accessibility/">GOV.UK’s posters</a> with accessibility dos and don’ts are just one of the many useful resources you’ll find in <a href="https://stephaniewalter.design/blog/neurodiversity-and-ux-essential-resources-for-cognitive-accessibility/">Stéphanie Walter’s collection</a>. (<a href="https://files.smashing.media/articles/designing-for-neurodiversity/2-neurodiversity-and-ux-essential-resources-for-cognitive-accessibility.png">Large preview</a>)<br />
    </figcaption></figure>
<p>Another fantastic resource is Will Soward’s <a href="https://neurodiversity.design/"><strong>Neurodiversity Design System</strong></a>. It combines neurodiversity and user experience design into a set of design standards and principles that you can use to design accessible learning interfaces.</p>
<p>Last but not least, I’ve been putting together a few summaries about <strong>neurodiversity and inclusive design</strong> over the last few years, so you might find them helpful, too:</p>
<ul>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-accessibility-activity-7188133636985028608-JEtj/">ADHD</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-design-accessibility-activity-7099294629887397888-L1d0/">Autism</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-design-activity-7156651715486732288-RvW7/">Children</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-design-accessibility-activity-7087333591906430976-PHsN">Colorblindness</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-accessibility-activity-7178702360649547778-4JtQ">Deafness</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-design-accessibility-activity-7111249864855810048-5qup">Dyscalculia</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-design-accessibility-activity-7079355423534784512-3R4C">Dyslexia</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-design-typography-activity-7095664890727526400-ECAH">Legibility</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-design-activity-7132292750355378176-ZMkL">Left-Handed Users</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-design-designpatterns-activity-7088778491109720064-im2_">Mental Health</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-design-learning-activity-7105272692919914496-Q2-y/">Motivation</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-design-accessibility-activity-7089866429016989696-JRAq">Older Adults</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_how-screen-readers-work-and-how-activity-7130472748371341312-i0PW">Screen Readers</a></li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-design-activity-7160904166075232256-mNMc">Teenagers</a></li>
</ul>
<p>A huge thank-you to everyone who has been writing, speaking, and sharing articles, resources, and toolkits on designing for diversity. The topic is often forgotten and overlooked, but it has an incredible impact. <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f44f-1f3fc.png" alt="👏🏼" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f44f-1f3fd.png" alt="👏🏽" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f44f-1f3fe.png" alt="👏🏾" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<div class="signature">
  <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 />
  <span>(vf, il, yk)</span>
</div>
</article>
]]></content:encoded>
					
					<wfw:commentRss>http://computercoursesonline.com/index.php/2025/06/02/designing-for-neurodiversity/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Reliably Detecting Third-Party Cookie Blocking In 2025</title>
		<link>http://computercoursesonline.com/index.php/2025/05/28/reliably-detecting-third-party-cookie-blocking-in-2025/</link>
					<comments>http://computercoursesonline.com/index.php/2025/05/28/reliably-detecting-third-party-cookie-blocking-in-2025/#respond</comments>
		
		<dc:creator><![CDATA[.]]></dc:creator>
		<pubDate>Wed, 28 May 2025 10:00:00 +0000</pubDate>
				<category><![CDATA[Ux]]></category>
		<guid isPermaLink="false">http://computercoursesonline.com/?p=928</guid>

					<description><![CDATA[Reliably Detecting Third-Party Cookie Blocking In 2025 Reliably Detecting Third-Party Cookie Blocking In 2025 Mikhail Prosmitskiy 2025-05-28T10:00:00+00:00 2025-05-29T20:32:50+00:00 The web is beginning to part ways with third-party cookies, a technology it once heavily relied on. Introduced in 1994 by Netscape to support features like virtual shopping carts, cookies have long been a staple of web functionality. However, concerns over...]]></description>
										<content:encoded><![CDATA[<p>              <title>Reliably Detecting Third-Party Cookie Blocking In 2025</title></p>
<article>
<header>
<h1>Reliably Detecting Third-Party Cookie Blocking In 2025</h1>
<address>Mikhail Prosmitskiy</address>
<p>                  2025-05-28T10:00:00+00:00<br />
                  2025-05-29T20:32:50+00:00<br />
                </header>
<p>The web is beginning to part ways with third-party cookies, a technology it once heavily relied on. <a href="https://en.wikipedia.org/wiki/HTTP_cookie">Introduced in 1994 by Netscape</a> to support features like virtual shopping carts, cookies have long been a staple of web functionality. However, concerns over <strong>privacy</strong> and <strong>security</strong> have led to a concerted effort to eliminate them. The World Wide Web Consortium Technical Architecture Group (W3C TAG) <a href="https://w3ctag.github.io/web-without-3p-cookies/">has been vocal in advocating</a> for the complete removal of third-party cookies from the web platform.</p>
<p>Major browsers (Chrome, Safari, Firefox, and Edge) are responding by phasing them out, though the transition is gradual. While this shift enhances user privacy, it also disrupts legitimate functionalities that rely on third-party cookies, such as single sign-on (SSO), fraud prevention, and embedded services. And because there is still no universal ban in place and many essential web features continue to depend on these cookies, developers must detect when third-party cookies are blocked so that applications can respond gracefully.</p>
<h2 id="don-t-let-silent-failures-win-why-cookie-detection-still-matters">Don’t Let Silent Failures Win: Why Cookie Detection Still Matters</h2>
<p>Yes, the ideal solution is to move away from third-party cookies altogether and redesign our integrations using privacy-first, purpose-built alternatives as soon as possible. But in reality, that migration can take months or even years, especially for legacy systems or third-party vendors. Meanwhile, users are already browsing with third-party cookies disabled and often have no idea that anything is missing.</p>
<p>Imagine a travel booking platform that embeds an iframe from a third-party partner to display live train or flight schedules. This embedded service uses a cookie on its own domain to authenticate the user and personalize content, like showing saved trips or loyalty rewards. But when the browser blocks third-party cookies, the iframe cannot access that data. Instead of a seamless experience, the user sees an error, a blank screen, or a login prompt that doesn’t work.</p>
<p>And while your team is still planning a long-term integration overhaul, this is already happening to real users. They don’t see a cookie policy; they just see a broken booking flow.</p>
<blockquote class="pull-quote">
<p>
    <a class="pull-quote__link" aria-label="Share on Twitter" href="https://twitter.com/share?text=%0aDetecting%20third-party%20cookie%20blocking%20isn%e2%80%99t%20just%20good%20technical%20hygiene%20but%20a%20frontline%20defense%20for%20user%20experience.%0a&amp;url=https://smashingmagazine.com%2f2025%2f05%2freliably-detecting-third-party-cookie-blocking-2025%2f"></p>
<p>Detecting third-party cookie blocking isn’t just good technical hygiene but a frontline defense for user experience.</p>
<p>    </a>
  </p>
<div class="pull-quote__quotation">
<div class="pull-quote__bg">
      <span class="pull-quote__symbol">“</span></div>
</p></div>
</blockquote>
<h2 id="why-it-s-hard-to-tell-if-third-party-cookies-are-blocked">Why It’s Hard To Tell If Third-Party Cookies Are Blocked</h2>
<p>Detecting whether third-party cookies are supported isn’t as simple as calling <a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/cookieEnabled"><code>navigator.cookieEnabled</code></a>. Even a well-intentioned check like this one may look safe, but it still won’t tell you what you actually need to know:</p>
<div class="break-out">
<pre><code class="language-javascript">// DOES NOT detect third-party cookie blocking
function areCookiesEnabled() {
  if (navigator.cookieEnabled === false) {
    return false;
  }

  try {
    document.cookie = "test&#095;cookie=1; SameSite=None; Secure";
    const hasCookie = document.cookie.includes("test&#095;cookie=1");
    document.cookie = "test&#095;cookie=; Max-Age=0; SameSite=None; Secure";

    return hasCookie;
  } catch (e) {
    return false;
  }
}
</code></pre>
</div>
<p>This function only confirms that cookies work in the current (first-party) context. <strong>It says nothing about third-party scenarios</strong>, like an iframe on another domain. Worse, it’s misleading: in some browsers, <code>navigator.cookieEnabled</code> may still return <code>true</code> inside a third-party iframe even when cookies are blocked. Others might behave differently, leading to inconsistent and unreliable detection.</p>
<p>These cross-browser inconsistencies &mdash; combined with the limitations of <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie"><code>document.cookie</code></a> &mdash; make it clear that there is <strong>no shortcut for detection</strong>. To truly detect third-party cookie blocking, we need to understand <em>how</em> different browsers actually behave in embedded third-party contexts.</p>
<div data-audience="non-subscriber" data-remove="true" class="feature-panel-container">
<aside class="feature-panel">
<div class="feature-panel-left-col">
<div class="feature-panel-description">
<p>Meet <strong><a data-instant href="https://www.smashingconf.com/online-workshops/">Smashing Workshops</a></strong> on <strong>front-end, design &amp; UX</strong>, with practical takeaways, live sessions, <strong>video recordings</strong> and a friendly Q&amp;A. With Brad Frost, Stéph Walter and <a href="https://smashingconf.com/online-workshops/workshops">so many others</a>.</p>
<p><a data-instant href="smashing-workshops" class="btn btn--green btn--large">Jump to the workshops&nbsp;↬</a></div>
</div>
<div class="feature-panel-right-col"><a data-instant href="smashing-workshops" class="feature-panel-image-link"></p>
<div class="feature-panel-image">
<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>
</div>
<p></a>
</div>
</aside>
</div>
<h2 id="how-modern-browsers-handle-third-party-cookies">How Modern Browsers Handle Third-Party Cookies</h2>
<p>The behavior of modern browsers directly affects which detection methods will work and which ones silently fail.</p>
<h3 id="safari-full-third-party-cookie-blocking">Safari: Full Third-Party Cookie Blocking</h3>
<p>Since <a href="https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/">version 13.1</a>, Safari blocks all third-party cookies by default, with no exceptions, even if the user previously interacted with the embedded domain. This policy is part of <a href="https://webkit.org/tracking-prevention/#intelligent-tracking-prevention-itp">Intelligent Tracking Prevention (ITP)</a>.</p>
<p>For embedded content (such as an SSO iframe) that requires cookie access, Safari exposes the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API">Storage Access API</a>, which requires a user gesture to grant storage permission. As a result, a test for third-party cookie support will nearly always fail in Safari unless the iframe explicitly requests access via this API.</p>
<h3 id="firefox-cookie-partitioning-by-design">Firefox: Cookie Partitioning By Design</h3>
<p>Firefox’s <a href="https://support.mozilla.org/en-US/kb/total-cookie-protection-and-website-breakage-faq#w_what-is-total-cookie-protection">Total Cookie Protection</a> isolates cookies on a per-site basis. Third-party cookies can still be set and read, but they are partitioned by the top-level site, meaning a cookie set by the same third-party on <em>siteA.com</em> and <em>siteB.com</em> is stored separately and cannot be shared.</p>
<p>As of <a href="https://support.mozilla.org/en-US/kb/introducing-total-cookie-protection-standard-mode">Firefox 102</a>, this behavior is enabled by default in the Standard (default) mode of <a href="https://support.mozilla.org/en-US/kb/enhanced-tracking-protection-firefox-desktop">Enhanced Tracking Protection</a>. Unlike the Strict mode &mdash; which <a href="https://support.mozilla.org/en-US/kb/enhanced-tracking-protection-firefox-desktop#w_strict-enhanced-tracking-protection">blocks third-party cookies entirely</a>, similar to Safari &mdash; the Standard mode does not block them outright. Instead, it neutralizes their tracking capability by isolating them per site.</p>
<p>As a result, even if a test shows that a third-party cookie was successfully set, it may be useless for cross-site logins or shared sessions due to this <strong>partitioning</strong>. Detection logic needs to account for that.</p>
<h3 id="chrome-from-deprecation-plans-to-privacy-sandbox-and-industry-pushback">Chrome: From Deprecation Plans To Privacy Sandbox (And Industry Pushback)</h3>
<p>Chromium-based browsers still allow third-party cookies by default &mdash; but the story is changing. Starting with <a href="https://blog.chromium.org/2019/10/developers-get-ready-for-new.html">Chrome 80</a>, third-party cookies must be explicitly marked with <code>SameSite=None; Secure</code>, or they will be rejected.</p>
<p>In <a href="https://blog.chromium.org/2020/01/building-more-private-web-path-towards.html">January 2020</a>, <strong>Google announced their intention</strong> to phase out third-party cookies by 2022. <strong>However, the timeline was updated multiple times</strong>, first in <a href="https://blog.google/products/chrome/updated-timeline-privacy-sandbox-milestones/?utm_source=chatgpt.com">June 2021</a> when the company pushed the rollout to begin in mid-2023 and conclude by the end of that year. Additional postponements followed in <a href="https://blog.google/products/chrome/update-testing-privacy-sandbox-web/">July 2022</a>, <a href="https://blog.google/products/chrome/privacy-sandbox-tracking-protection/">December 2023</a>, and <a href="https://privacysandbox.com/intl/en_us/news/update-on-the-plan-for-phase-out-of-third-party-cookies-on-chrome/">April 2024</a>.</p>
<p>In <a href="https://privacysandbox.com/news/privacy-sandbox-update/">July 2024</a>, <strong>Google has clarified that there is no plan to unilaterally deprecate third-party cookies or force users into a new model without consent</strong>. Instead, Chrome is shifting to a <strong>user-choice interface</strong> that will allow individuals to decide whether to block or allow third-party cookies globally.</p>
<p>This change was influenced in part by <a href="https://www.businessinsider.com/googles-plan-to-replace-tracking-cookies-faces-big-new-hurdles-2024-7">substantial pushback from the advertising industry</a>, as well as ongoing regulatory oversight, including <a href="https://www.gov.uk/cma-cases/investigation-into-googles-privacy-sandbox-browser-changes">scrutiny by the UK Competition and Markets Authority (CMA)</a> into <a href="https://privacysandbox.google.com">Google’s Privacy Sandbox initiative</a>. The CMA confirmed in a 2025 update that there is no intention to force a deprecation or trigger automatic prompts for cookie blocking.</p>
<p>As for now, <strong>third-party cookies remain enabled by default in Chrome</strong>. The new user-facing controls and the broader Privacy Sandbox ecosystem are still in various stages of experimentation and limited rollout.</p>
<h3 id="edge-chromium-based-tracker-focused-blocking-with-user-configurability">Edge (Chromium-Based): Tracker-Focused Blocking With User Configurability</h3>
<p>Edge (which is a Chromium-based browser) <a href="https://learn.microsoft.com/en-us/microsoftteams/platform/resources/samesite-cookie-update#samesite-cookie-attribute-2020-release">shares Chrome’s handling of third-party cookies</a>, including the <code>SameSite=None; Secure</code> requirement. Additionally, Edge introduces <a href="https://learn.microsoft.com/en-us/microsoft-edge/web-platform/tracking-prevention">Tracking Prevention</a> modes: Basic, Balanced (default), and Strict. In Balanced mode, it blocks known third-party trackers using Microsoft’s maintained list but allows many third-party cookies that are not classified as trackers. Strict mode blocks more resource loads than Balanced, which may result in some websites not behaving as expected.</p>
<h3 id="other-browsers-what-about-them">Other Browsers: What About Them?</h3>
<p>Privacy-focused browsers, like Brave, <a href="https://support.brave.com/hc/en-us/articles/360054509991-How-do-I-manage-Cookies-and-Site-data-in-Brave-on-Android?utm_source=chatgpt.com">block third-party cookies by default</a> as part of their strong anti-tracking stance.</p>
<p>Internet Explorer (IE) 11 <a href="https://support.microsoft.com/en-us/topic/description-of-cookies-ad01aa7e-66c9-8ab2-7898-6652c100999d">allowed third-party cookies depending on user privacy settings</a> and the presence of <a href="https://www.w3.org/P3P/">Platform for Privacy Preferences (P3P)</a> headers. However, IE usage is now negligible. Notably, the default “Medium” privacy setting in IE could block third-party cookies unless a valid P3P policy was present.</p>
<p>Older versions of Safari had partial third-party cookie restrictions (such as <em>“Allow from websites I visit”</em>), but, as mentioned before, this was replaced with full blocking via ITP.</p>
<p><strong>As of 2025, all major browsers either block or isolate third-party cookies by default, with the exception of Chrome, which still allows them in standard browsing mode pending the rollout of its new user-choice model.</strong></p>
<p>To account for these variations, your detection strategy must be grounded in real-world testing &mdash; specifically by reproducing a genuine third-party context such as loading your script within an iframe on a cross-origin domain &mdash; rather than relying on browser names or versions.</p>
<div class="partners__lead-place"></div>
<h2 id="overview-of-detection-techniques">Overview Of Detection Techniques</h2>
<p>Over the years, many techniques have been used to detect third-party cookie blocking. Most are unreliable or obsolete. Here’s a quick walkthrough of what doesn’t work (and why) and what does.</p>
<h3 id="basic-javascript-api-checks-misleading">Basic JavaScript API Checks (Misleading)</h3>
<p>As mentioned earlier, the <code>navigator.cookieEnabled</code> or setting <code>document.cookie</code> on the main page doesn’t reflect cross-site cookie status:</p>
<ul>
<li>In third-party iframes, <code>navigator.cookieEnabled</code> often returns <code>true</code> even when cookies are blocked.</li>
<li>Setting <code>document.cookie</code> in the parent doesn’t test the third-party context.</li>
</ul>
<p>These checks are first-party only. <strong>Avoid using them for detection.</strong></p>
<h3 id="storage-hacks-via-localstorage-obsolete">Storage Hacks Via <code>localStorage</code> (Obsolete)</h3>
<p>Previously, some developers inferred cookie support by checking if <code>window.localStorage</code> worked inside a third-party iframe &mdash; which is especially useful against older Safari versions that blocked all third-party storage.</p>
<p>Modern browsers often allow <code>localStorage</code> even when cookies are blocked. <strong>This leads to false positives and is no longer reliable.</strong></p>
<h3 id="server-assisted-cookie-probe-heavyweight">Server-Assisted Cookie Probe (Heavyweight)</h3>
<p>One classic method involves setting a cookie from a third-party domain via HTTP and then checking if it comes back:</p>
<ol>
<li>Load a script/image from a third-party server that sets a cookie.</li>
<li>Immediately load another resource, and the server checks whether the cookie was sent.</li>
</ol>
<p>This works, but it:</p>
<ul>
<li>Requires custom server-side logic,</li>
<li>Depends on HTTP caching, response headers, and cookie attributes (<code>SameSite=None; Secure</code>), and</li>
<li>Adds development and infrastructure complexity.</li>
</ul>
<p>While this is <strong>technically valid</strong>, it is not suitable for a front-end-only approach, which is our focus here.</p>
<h3 id="storage-access-api-supplemental-signal">Storage Access API (Supplemental Signal)</h3>
<p>The <code>document.hasStorageAccess()</code> method allows embedded third-party content to check if it has access to unpartitioned cookies:</p>
<ul>
<li><strong>Chrome</strong><br />
Supports <code>hasStorageAccess()</code> and <code>requestStorageAccess()</code> starting from <a href="https://privacysandbox.google.com/cookies/storage-access-api#top-level_page_access">version 119</a>. Additionally, <code>hasUnpartitionedCookieAccess()</code> is available as an alias for <code>hasStorageAccess()</code> from <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/hasUnpartitionedCookieAccess#browser_compatibility">version 125</a> onwards.</li>
<li><strong>Firefox</strong><br />
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API#browser_compatibility">Supports</a> both <code>hasStorageAccess()</code> and <code>requestStorageAccess()</code> methods.</li>
<li><strong>Safari</strong><br />
<a href="https://webkit.org/blog/11545/updates-to-the-storage-access-api/">Supports the Storage Access API</a>. However, <strong>access must always be triggered by a user interaction</strong>. For example, even calling <code>requestStorageAccess()</code> without a direct user gesture (like a click) is ignored.</li>
</ul>
<p>Chrome and Firefox also support the API, and in those browsers, it may work automatically or based on browser heuristics or site engagement.</p>
<p>This API is particularly useful for detecting scenarios where cookies are present but partitioned (e.g., Firefox’s Total Cookie Protection), as it helps determine if the iframe has unrestricted cookie access. But for now, it’s still best used as a <strong>supplemental signal</strong>, rather than a standalone check.</p>
<h3 id="iframe-postmessage-best-practice">iFrame + <code>postMessage</code> (Best Practice)</h3>
<p>Despite the existence of the Storage Access API, <strong>at the time of writing, this remains the most reliable and browser-compatible method</strong>:</p>
<ol>
<li>Embed a hidden iframe from a third-party domain.</li>
<li>Inside the iframe, attempt to set a test cookie.</li>
<li>Use <code>window.postMessage</code> to report success or failure to the parent.</li>
</ol>
<p>This approach works across all major browsers (when properly configured), requires no server (kind of, more on that next), and simulates a real-world third-party scenario.</p>
<p>We’ll implement this step-by-step next.</p>
<h3 id="bonus-sec-fetch-storage-access">Bonus: <code>Sec-Fetch-Storage-Access</code></h3>
<p>Chrome (starting in <a href="https://privacysandbox.google.com/blog/storage-access-headers-133">version 133</a>) is introducing <code>Sec-Fetch-Storage-Access</code>, an HTTP request header sent with cross-site requests to indicate whether the iframe has access to unpartitioned cookies. <strong>This header is only visible to servers and cannot be accessed via JavaScript.</strong> It’s useful for back-end analytics but not applicable for client-side cookie detection.</p>
<p>As of May 2025, this feature is only implemented in Chrome and is not supported by other browsers. However, it’s still good to know that it’s part of the evolving ecosystem.</p>
<h2 id="step-by-step-detecting-third-party-cookies-via-iframe">Step-by-Step: Detecting Third-Party Cookies Via iFrame</h2>
<p>So, what did I mean when I said that the last method we looked at “requires no server”? While this method doesn’t require any back-end logic (like server-set cookies or response inspection), it does require access to a separate domain &mdash; or at least a cross-site subdomain &mdash; to simulate a third-party environment. This means the following:</p>
<ul>
<li>You must serve the test page from a different domain or public subdomain, e.g., <code>example.com</code> and <code>cookietest.example.com</code>,</li>
<li>The domain needs HTTPS (for <code>SameSite=None; Secure</code> cookies to work), and</li>
<li>You’ll need to host a simple static file (the test page), even if no server code is involved.</li>
</ul>
<p>Once that’s set up, the rest of the logic is fully client-side.</p>
<h3 id="step-1-create-a-cookie-test-page-on-a-third-party-domain">Step 1: Create A Cookie Test Page (On A Third-Party Domain)</h3>
<p>Minimal version (e.g., <code>https://cookietest.example.com/cookie-check.html</code>):</p>
<div class="break-out">
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;body&gt;
    &lt;script&gt;
      document.cookie = "thirdparty&#095;test=1; SameSite=None; Secure; Path=/;";
      const cookieFound = document.cookie.includes("thirdparty&#095;test=1");
    
      const sendResult = (status) =&gt; window.parent?.postMessage(status, "&#042;");
    
      if (cookieFound &amp;&amp; document.hasStorageAccess instanceof Function) {
        document.hasStorageAccess().then((hasAccess) =&gt; {
          sendResult(hasAccess ? "TP&#095;COOKIE&#095;SUPPORTED" : "TP&#095;COOKIE&#095;BLOCKED");
        }).catch(() =&gt; sendResult("TP&#095;COOKIE&#095;BLOCKED"));
      } else {
        sendResult(cookieFound ? "TP&#095;COOKIE_SUPPORTED" : "TP&#095;COOKIE_BLOCKED");
      }
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre>
</div>
<p>Make sure the page is served over HTTPS, and the cookie uses <code>SameSite=None; Secure</code>. Without these attributes, modern browsers will silently reject it.</p>
<h3 id="step-2-embed-the-iframe-and-listen-for-the-result">Step 2: Embed The iFrame And Listen For The Result</h3>
<p>On your main page:</p>
<div class="break-out">
<pre><code class="language-javascript">function checkThirdPartyCookies() {
  return new Promise((resolve) =&gt; {
    const iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    iframe.src = "https://cookietest.example.com/cookie-check.html"; // your subdomain
    document.body.appendChild(iframe);

    let resolved = false;
    const cleanup = (result, timedOut = false) =&gt; {
      if (resolved) return;
      resolved = true;
      window.removeEventListener('message', onMessage);
      iframe.remove();
      resolve({ thirdPartyCookiesEnabled: result, timedOut });
    };

    const onMessage = (event) =&gt; {
      if (["TP&#095;COOKIE&#095;SUPPORTED", "TP&#095;COOKIE&#095;BLOCKED"].includes(event.data)) {
        cleanup(event.data === "TP&#095;COOKIE&#095;SUPPORTED", false);
      }
    };

    window.addEventListener('message', onMessage);
    setTimeout(() =&gt; cleanup(false, true), 1000);
  });
}
</code></pre>
</div>
<p>Example usage:</p>
<div class="break-out">
<pre><code class="language-javascript">checkThirdPartyCookies().then(({ thirdPartyCookiesEnabled, timedOut }) =&gt; {
  if (!thirdPartyCookiesEnabled) {
    someCookiesBlockedCallback(); // Third-party cookies are blocked.
    if (timedOut) {
      // No response received (iframe possibly blocked).
      // Optional fallback UX goes here.
      someCookiesBlockedTimeoutCallback();
    };
  }
});
</code></pre>
</div>
<h3 id="step-3-enhance-detection-with-the-storage-access-api">Step 3: Enhance Detection With The Storage Access API</h3>
<p>In Safari, even when third-party cookies are blocked, users can manually grant access through the Storage Access API &mdash; but only in response to a user gesture.</p>
<p>Here’s how you could implement that in your iframe test page:</p>
<div class="break-out">
<pre><code class="language-html">&lt;button id="enable-cookies"&gt;This embedded content requires cookie access. Click below to continue.&lt;/button&gt;

&lt;script&gt;
  document.getElementById('enable-cookies')?.addEventListener('click', async () =&gt; {
    if (document.requestStorageAccess &amp;&amp; typeof document.requestStorageAccess === 'function') {
      try {
        const granted = await document.requestStorageAccess();
        if (granted !== false) {
          window.parent.postMessage("TP&#095;STORAGE&#095;ACCESS&#095;GRANTED", "&#042;");
        } else {
          window.parent.postMessage("TP&#095;STORAGE&#095;ACCESS&#095;DENIED", "&#042;");
        }
      } catch (e) {
        window.parent.postMessage("TP&#095;STORAGE&#095;ACCESS&#095;FAILED", "&#042;");
      }
    }
  });
&lt;/script&gt;
</code></pre>
</div>
<p>Then, on the parent page, you can listen for this message and retry detection if needed:</p>
<div class="break-out">
<pre><code class="language-javascript">// Inside the same `onMessage` listener from before:
if (event.data === "TP&#095;STORAGE&#095;ACCESS&#095;GRANTED") {
  // Optionally: retry the cookie test, or reload iframe logic
  checkThirdPartyCookies().then(handleResultAgain);
}
</code></pre>
</div>
<div class="partners__lead-place"></div>
<h2 id="bonus-a-purely-client-side-fallback-not-perfect-but-sometimes-necessary">(Bonus) A Purely Client-Side Fallback (Not Perfect, But Sometimes Necessary)</h2>
<p>In some situations, you might not have access to a second domain or can’t host third-party content under your control. That makes the iframe method unfeasible.</p>
<p>When that’s the case, your best option is to <strong>combine multiple signals</strong> &mdash; basic cookie checks, <code>hasStorageAccess()</code>, <code>localStorage</code> fallbacks, and maybe even passive indicators like load failures or timeouts &mdash; to <strong>infer</strong> whether third-party cookies are likely blocked.</p>
<p>The important caveat: <strong>This will never be 100% accurate.</strong> But, in constrained environments, “better something than nothing” may still improve the UX.</p>
<p>Here’s a basic example:</p>
<div class="break-out">
<pre><code class="language-javascript">async function inferCookieSupportFallback() {
  let hasCookieAPI = navigator.cookieEnabled;
  let canSetCookie = false;
  let hasStorageAccess = false;

  try {
    document.cookie = "testfallback=1; SameSite=None; Secure; Path=/;";
    canSetCookie = document.cookie.includes("test&#095;fallback=1");

    document.cookie = "test&#095;fallback=; Max-Age=0; Path=/;";
  } catch (&#095;) {
    canSetCookie = false;
  }

  if (typeof document.hasStorageAccess === "function") {
    try {
      hasStorageAccess = await document.hasStorageAccess();
    } catch (&#095;) {}
  }

  return {
    inferredThirdPartyCookies: hasCookieAPI &amp;&amp; canSetCookie &amp;&amp; hasStorageAccess,
    raw: { hasCookieAPI, canSetCookie, hasStorageAccess }
  };
}
</code></pre>
</div>
<p>Example usage:</p>
<div class="break-out">
<pre><code class="language-javascript">inferCookieSupportFallback().then(({ inferredThirdPartyCookies }) =&gt; {
  if (inferredThirdPartyCookies) {
    console.log("Cookies likely supported. Likely, yes.");
  } else {
    console.warn("Cookies may be blocked or partitioned.");
    // You could inform the user or adjust behavior accordingly
  }
});
</code></pre>
</div>
<p>Use this fallback when:</p>
<ul>
<li>You’re building a JavaScript-only widget embedded on unknown sites,</li>
<li>You don’t control a second domain (or the team refuses to add one), or</li>
<li>You just need <em>some</em> visibility into user-side behavior (e.g., debugging UX issues).</li>
</ul>
<p><strong>Don’t rely on it for security-critical logic (e.g., auth gating)!</strong> But it may help tailor the user experience, surface warnings, or decide whether to attempt a fallback SSO flow. Again, it’s better to have something rather than nothing.</p>
<h2 id="fallback-strategies-when-third-party-cookies-are-blocked">Fallback Strategies When Third-Party Cookies Are Blocked</h2>
<p>Detecting blocked cookies is only half the battle. Once you know they’re unavailable, what can you do? Here are some practical options that might be useful for you:</p>
<h3 id="redirect-based-flows">Redirect-Based Flows</h3>
<p>For auth-related flows, switch from embedded iframes to top-level redirects. Let the user authenticate directly on the identity provider&rsquo;s site, then redirect back. It works in all browsers, but the UX might be less seamless.</p>
<h3 id="request-storage-access">Request Storage Access</h3>
<p>Prompt the user using <code>requestStorageAccess()</code> after a clear UI gesture (Safari requires this). Use this to re-enable cookies <strong>without leaving the page</strong>.</p>
<h3 id="token-based-communication">Token-Based Communication</h3>
<p>Pass session info directly from parent to iframe via:</p>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage"><code>postMessage</code></a> (with required <a href="https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/11-Testing_Web_Messaging"><code>origin</code></a>);</li>
<li>Query params (e.g., signed JWT in iframe URL).</li>
</ul>
<p>This avoids reliance on cookies entirely but requires coordination between both sides:</p>
<div class="break-out">
<pre><code class="language-javascript">// Parent
const iframe = document.getElementById('my-iframe');

iframe.onload = () =&gt; {
  const token = getAccessTokenSomehow(); // JWT or anything else
  iframe.contentWindow.postMessage(
    { type: 'AUTH&#095;TOKEN', token },
    'https://iframe.example.com' // Set the correct origin!
  );
};

// iframe
window.addEventListener('message', (event) =&gt; {
  if (event.origin !== 'https://parent.example.com') return;

  const { type, token } = event.data;

  if (type === 'AUTH&#095;TOKEN') {
    validateAndUseToken(token); // process JWT, init session, etc
  }
});
</code></pre>
</div>
<h3 id="partitioned-cookies-chips">Partitioned Cookies (CHIPS)</h3>
<p>Chrome (since version 114) and other Chromium-based browsers now support cookies with the Partitioned attribute (known as <a href="https://privacysandbox.google.com/cookies/chips">CHIPS</a>), allowing per-top-site cookie isolation. This is useful for widgets like chat or embedded forms where cross-site identity isn’t needed.</p>
<blockquote><p><strong>Note</strong>: Firefox and Safari don’t support the <code>Partitioned</code> cookie attribute. Firefox enforces cookie partitioning by default using a different mechanism (Total Cookie Protection), while Safari blocks third-party cookies entirely.</p></blockquote>
<p>But be careful, as they are treated as “blocked” by basic detection. Refine your logic if needed.</p>
<h2 id="final-thought-transparency-transition-and-the-path-forward">Final Thought: Transparency, Transition, And The Path Forward</h2>
<p>Third-party cookies are disappearing, albeit gradually and unevenly. Until the transition is complete, your job as a developer is to bridge the gap between technical limitations and real-world user experience. That means:</p>
<ul>
<li><strong>Keep an eye on the standards.</strong><br />
APIs like <a href="https://privacysandbox.google.com/cookies/fedcm">FedCM</a> and Privacy Sandbox features (<a href="https://privacysandbox.google.com/private-advertising/topics?hl=en">Topics</a>, <a href="https://privacysandbox.google.com/private-advertising/attribution-reporting">Attribution Reporting</a>, <a href="https://privacysandbox.google.com/private-advertising/fenced-frame">Fenced Frames</a>) are reshaping how we handle identity and analytics without relying on cross-site cookies.</li>
<li><strong>Combine detection with graceful fallback.</strong><br />
Whether it’s offering a redirect flow, using <code>requestStorageAccess()</code>, or falling back to token-based messaging &mdash; every small UX improvement adds up.</li>
<li><strong>Inform your users.</strong><br />
Users shouldn&rsquo;t be left wondering why something worked in one browser but silently broke in another. Don’t let them feel like they did something wrong &mdash; just help them move forward. A clear, friendly message can prevent this confusion.</li>
</ul>
<p>The good news? You don’t need a perfect solution today, just a resilient one. By detecting issues early and handling them thoughtfully, you protect both your users and your future architecture, one cookie-less browser at a time.</p>
<p>And as seen with Chrome’s pivot away from automatic deprecation, the transition is not always linear. Industry feedback, regulatory oversight, and evolving technical realities continue to shape the time and the solutions.</p>
<p>And don’t forget: <em>having something is better than nothing</em>.</p>
<div class="signature">
  <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 />
  <span>(yk)</span>
</div>
</article>
]]></content:encoded>
					
					<wfw:commentRss>http://computercoursesonline.com/index.php/2025/05/28/reliably-detecting-third-party-cookie-blocking-in-2025/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Data Vs. Findings Vs. Insights In UX</title>
		<link>http://computercoursesonline.com/index.php/2025/05/27/data-vs-findings-vs-insights-in-ux/</link>
					<comments>http://computercoursesonline.com/index.php/2025/05/27/data-vs-findings-vs-insights-in-ux/#respond</comments>
		
		<dc:creator><![CDATA[.]]></dc:creator>
		<pubDate>Tue, 27 May 2025 13:00:00 +0000</pubDate>
				<category><![CDATA[Ux]]></category>
		<guid isPermaLink="false">http://computercoursesonline.com/?p=930</guid>

					<description><![CDATA[Data Vs. Findings Vs. Insights In UX Data Vs. Findings Vs. Insights In UX Vitaly Friedman 2025-05-27T13:00:00+00:00 2025-05-29T20:32:50+00:00 In many companies, data, findings, and insights are all used interchangeably. Slack conversations circle around convincing data points, statistically significant findings, reliable insights, and emerging trends. Unsurprisingly, conversations often mistake sporadic observations for consistent patterns. But how...]]></description>
										<content:encoded><![CDATA[<p>              <title>Data Vs. Findings Vs. Insights In UX</title></p>
<article>
<header>
<h1>Data Vs. Findings Vs. Insights In UX</h1>
<address>Vitaly Friedman</address>
<p>                  2025-05-27T13:00:00+00:00<br />
                  2025-05-29T20:32:50+00:00<br />
                </header>
<p>In many companies, <strong>data, findings, and insights</strong> are all used interchangeably. Slack conversations circle around convincing data points, statistically significant findings, reliable insights, and emerging trends. Unsurprisingly, conversations often <strong>mistake sporadic observations</strong> for consistent patterns.</p>
<p>But how impactful is the weight that each of them carries? And how do we <strong>turn raw data into meaningful insights</strong> to make better decisions? Well, let’s find out.</p>
<figure class="
  
  
  "></p>
<p>    <a href="https://www.nngroup.com/videos/data-findings-insights/"></p>
<p>    <img loading="lazy" width="800" height="735" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Data vs. Findings vs. Insights" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/mailing-94-data-findings-insights/1-mailing-94-data-findings-insights.jpg"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      Data ≠ Findings ≠ Insights. <a href="https://www.nngroup.com/videos/data-findings-insights/">Short video by NN/g</a> explains the differences between them.(<a href="https://files.smashing.media/articles/mailing-94-data-findings-insights/1-mailing-94-data-findings-insights.jpg">Large preview</a>)<br />
    </figcaption></figure>
<h2 id="why-it-all-matters">Why It All Matters</h2>
<p>At first, it may seem that the differences are very nuanced and merely technical. But when we <strong>review inputs and communicate the outcomes of our UX work</strong>, we need to be careful not to conflate terminology &mdash; to avoid wrong assumptions, wrong conclusions, and early dismissals.</p>
<figure class="
  
  
  "></p>
<p>    <a href="https://swipefile.com/from-data-to-impact"></p>
<p>    <img loading="lazy" width="800" height="800" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Gapingvoid illustration" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/mailing-94-data-findings-insights/2-mailing-94-data-findings-insights.jpg"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      Raw data points is random and inconclusive. For it to be valuable, it must be turned into insights. Cartoon by <a href="https://swipefile.com/from-data-to-impact">Hugh MacLeod</a>. (<a href="https://files.smashing.media/articles/mailing-94-data-findings-insights/2-mailing-94-data-findings-insights.jpg">Large preview</a>)<br />
    </figcaption></figure>
<p>When <strong>strong recommendations and bold statements</strong> emerge in a big meeting, inevitably, there will be people questioning the decision-making process. More often than not, they will be the loudest voices in the room, often with their own agenda and priorities that they are trying to protect.</p>
<p>As UX designers, we need to be prepared for it. The last thing we want is to have a <strong>weak line of thinking</strong>, easily dismantled under the premise of “weak research”, “unreliable findings”, “poor choice of users” &mdash; and hence dismissed straight away.</p>
<h2 id="data-findings-insights">Data ≠ Findings ≠ Insights</h2>
<p>People with different roles &mdash; analysts, data scientists, researchers, strategists &mdash; often rely on fine distinctions to make their decisions. The general difference is easy to put together:</p>
<ul>
<li><strong>Data</strong> is raw observations (logs, notes, survey answers) (<em>what was recorded</em>).</li>
<li><strong>Findings</strong> describe emerging patterns in data but aren’t actionable (<em>what happened</em>).</li>
<li><strong>Insights</strong> are business opportunities (<em>what happened + why + so what</em>).</li>
<li><strong>Hindsights</strong> are reflections of past actions and outcomes (<em>what we learned in previous work</em>).</li>
<li><strong>Foresights</strong> are informed projections, insights with extrapolation (<em>what could happen next</em>).</li>
</ul>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://dataforest.ai/blog/what-impact-do-data-insights-have-on-business-development"></p>
<p>    <img loading="lazy" width="800" height="1011" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Data analytics value chart" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/mailing-94-data-findings-insights/3-mailing-94-data-findings-insights.jpg"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      Business value emerges from turning hindsights into insights, then insights into foresights. (Image source: <a href="https://dataforest.ai/blog/what-impact-do-data-insights-have-on-business-development">The Hidden Truth of Business</a>) (<a href="https://files.smashing.media/articles/mailing-94-data-findings-insights/3-mailing-94-data-findings-insights.jpg">Large preview</a>)<br />
    </figcaption></figure>
<p>Here’s what it then looks like in real life:</p>
<ul>
<li><strong>Data ↓</strong><br />
Six users were looking for ”Money transfer” in “Payments”, and <strong>4 users discovered</strong> the feature in their personal dashboard.</li>
<li><strong>Finding ↓</strong><br />
60% of users <strong>struggled to find</strong> the “Money transfer” feature on a dashboard, often confusing it with the “Payments” section.</li>
<li><strong>Insight ↓</strong><br />
Navigation doesn’t match users’ mental models for money transfers, causing confusion and delays. We recommend <strong>renaming sections or reorganizing the dashboard</strong> to prioritize “Transfer Money”. It could make task completion more intuitive and efficient.</li>
<li><strong>Hindsight ↓</strong><br />
After renaming the section to “Transfer Money” and moving it to the main dashboard, <strong>task success increased by 12%</strong>. User confusion dropped in follow-up tests. It proved to be an effective solution.</li>
<li><strong>Foresight ↓</strong><br />
As our financial products become more complex, users will expect simpler <strong>task-oriented navigation</strong> (e.g., “Send Money”, “Pay Bills“) instead of categories like “Payments”. We should evolve the dashboard towards action-driven IA to meet user expectations.</li>
</ul>
<p><strong>Only insights create understanding</strong> and drive strategy. Foresights shape strategy, too, but are always shaped by bets and assumptions. So, unsurprisingly, stakeholders are interested in insights, not findings. They rarely need to dive into raw data points. But often, they do want to make sure that <strong>findings are reliable</strong>.</p>
<p>That’s when, eventually, the big question about <strong>statistical significance</strong> comes along. And that’s when ideas and recommendations often get dismissed without a chance to be explored or explained.</p>
<div class="partners__lead-place"></div>
<h2 id="but-is-it-statistically-significant">But Is It Statistically Significant?</h2>
<p>Now, for UX designers, that’s an incredibly difficult question to answer. As Nikki Anderson <a href="https://www.linkedin.com/posts/nikkianderson-ux_is-this-statistically-significant-every-activity-7307757817434697729-qZk5/">pointed out</a>, statistical significance <strong>was never designed for qualitative research</strong>. And with UX work, we’re not trying to publish academic research or prove universal truths.</p>
<p>What we <em>are</em> trying to do is reach <strong>theoretical saturation</strong>, the point where additional research doesn’t give us new insights. Research isn’t about proving something is true. It’s about preventing costly mistakes before they happen.</p>
<figure class="
  
  
  "></p>
<p>    <a href="https://www.linkedin.com/posts/nikkianderson-ux_stop-calling-it-an-insight-if-its-just-activity-7317547275021344770-hiZI/"></p>
<p>    <img loading="lazy" width="800" height="707" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Data analytics value chart" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/mailing-94-data-findings-insights/4-mailing-94-data-findings-insights.jpg"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      <a href="https://www.linkedin.com/posts/nikkianderson-ux_stop-calling-it-an-insight-if-its-just-activity-7317547275021344770-hiZI/">Consequence cheat sheet by Nikki Anderson</a> for turning findings into insights. (<a href="https://files.smashing.media/articles/mailing-94-data-findings-insights/4-mailing-94-data-findings-insights.jpg">Large preview</a>)<br />
    </figcaption></figure>
<p>Here are some <strong>useful talking points</strong> to handle the question:</p>
<ul>
<li><strong>Five users per segment</strong> often <strong>surface major issues</strong>, and 10&ndash;15 users per segment usually reach saturation. If we’re still getting new insights after that, our scope is too broad.</li>
<li>“If five people hit the same pothole and wreck their car, how many more do you need before fixing the road?”</li>
<li>“If three enterprise customers say onboarding is confusing, that’s a <strong>churn risk</strong>.”</li>
<li>“If two usability tests expose a checkout issue, that’s <strong>abandoned revenue</strong>.”</li>
<li>“If one customer interview reveals a security concern, that’s a <strong>crisis waiting to happen</strong>.”</li>
<li>“How many user complaints exactly do we need to take this seriously?”</li>
<li>“How much revenue exactly are we willing to lose before fixing this issue?”</li>
</ul>
<p>And: it might not be necessary to focus on the number of participants, but instead, argue about <strong>users consistently struggling with a feature</strong>, mismatch of expectations, and a clear pattern emerging around a particular pain point.</p>
<h2 id="how-to-turn-findings-into-insights">How To Turn Findings Into Insights</h2>
<p>Once we notice patterns emerging, we need to turn them into actionable recommendations. Surprisingly, this isn’t always easy &mdash; we need to <strong>avoid easy guesses and assumptions</strong> as far as possible, as they will invite wrong conclusions.</p>
<p>To do that, you can rely on a very simple but effective framework to turn findings into insights: <strong>What Happened + Why + So What</strong>:</p>
<ul>
<li><strong>“What happened”</strong> covers observed behavior and patterns.</li>
<li><strong>“Why”</strong> includes beliefs, expectations, or triggers.</li>
<li><strong>“So What”</strong> addresses impact, risk, and business opportunity.</li>
</ul>
<p>To better assess the “so what” part, we should pay close attention to the impact of what we have noticed on desired business outcomes. It can be anything from high-impact blockers and confusion to <strong>hesitation and inaction</strong>.</p>
<p>I can wholeheartedly recommend exploring <strong>Findings → Insights Cheatsheet</strong> in <a href="https://www.linkedin.com/posts/nikkianderson-ux_stop-calling-it-an-insight-if-its-just-activity-7317547275021344770-hiZI/">Nikki Anderson’s wonderful slide deck</a>, which has examples and prompts to use to turn findings into insights.</p>
<h2 id="stop-sharing-findings-deliver-insights">Stop Sharing Findings — Deliver Insights</h2>
<p>When presenting the outcomes of your UX work, focus on <strong>actionable recommendations and business opportunities</strong> rather than patterns that emerged during testing.</p>
<p>To me, it’s all about telling a <strong>good damn story</strong>. Memorable, impactful, feasible, and convincing. Paint the picture of what the future could look like and the difference it would produce. That’s where the biggest impact of UX work emerges.</p>
<h2 id="how-to-measure-ux-and-design-impact">How To Measure UX And Design Impact</h2>
<p>Meet <a href="https://measure-ux.com/">Measure UX &amp; Design Impact</a> (8h), a <strong>practical guide for designers and UX leads</strong> to shape, measure, and explain your incredible UX impact on business. Recorded and updated by Vitaly Friedman. Use the friendly code <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f39f.png" alt="🎟" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong><code>IMPACT</code></strong> to <strong>save 20% off</strong> today. <a href="https://measure-ux.com">Jump to the details</a>.</p>
<figure style="margin-bottom:0;padding-bottom:0" class="break-out article__image">
    <a href="https://measure-ux.com/" title="How To Measure UX and Design Impact, with Vitaly Friedman"><br />
    <img loading="lazy" width="900" height="466" style="border-radius: 11px" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="How to Measure UX and Design Impact, with Vitaly Friedman." class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/04/measure-ux-and-design-impact-course.png"><br />
    </a><br />
</figure>
<div class="book-cta__inverted">
<div class="book-cta" data-handler="ContentTabs" data-mq="(max-width: 480px)">
<nav class="content-tabs content-tabs--books">
<ul>
<li class="content-tab"><a href="#"><button class="btn btn--small btn--white btn--white--bordered"><br />
Video + UX Training</button></a></li>
<li class="content-tab"><a href="#"><button class="btn btn--small btn--white btn--white--bordered">Video only</button></a></li>
</ul>
</nav>
<div class="book-cta__col book-cta__hardcover content-tab--content">
<h3 class="book-cta__title"><span>Video + UX Training</span></h3>
<p><span class="book-cta__price"><span><span class=""><span class="currency-sign">$</span>&nbsp;<span>495<span class="sup">.00</span></span></span> <span class="book-cta__price--old"><span class="currency-sign">$</span>&nbsp;<span>799<span class="sup">.00</span></span></span></span></span><br />
<a href="https://smart-interface-design-patterns.thinkific.com/enroll/3081832?price_id=3951439" class="btn btn--full btn--medium btn--text-shadow"><br />
Get Video + UX Training</p>
<div></div>
<p></a></p>
<p class="book-cta__desc">25 video lessons (8h) + <a href="https://smashingconf.com/online-workshops/workshops/vitaly-friedman-impact-design/">Live UX Training</a>.<br />100 days money-back-guarantee.</p>
</div>
<div class="book-cta__col book-cta__ebook content-tab--content">
<h3 class="book-cta__title"><span>Video only</span></h3>
<div data-audience="anonymous free supporter" data-remove="true"><span class="book-cta__price" data-handler="PriceTag"><span><span class=""><span class="currency-sign">$</span>&nbsp;<span>250<span class="sup">.00</span></span></span><span class="book-cta__price--old"><span class="currency-sign">$</span>&nbsp;<span>395<span class="sup">.00</span></span></span></span></span></div>
<p><a href="https://smart-interface-design-patterns.thinkific.com/enroll/3081832?price_id=3950630" class="btn btn--full btn--medium btn--text-shadow"><br />
Get the video course</p>
<div></div>
<p></a></p>
<p class="book-cta__desc" data-audience="anonymous free supporter" data-remove="true">25 video lessons (8h). Updated yearly.<br />Also available as a <a href="https://smart-interface-design-patterns.thinkific.com/enroll/3082557?price_id=3951421">UX Bundle with 2 video courses.</a></p>
</div>
<p><span></span></div>
</div>
<h3 id="further-reading-on-smashing-magazine">Further Reading on Smashing Magazine</h3>
<ul>
<li>“<a href="https://www.smashingmagazine.com/2025/02/human-element-using-research-psychology-elevate-data-storytelling/">The Human Element: Using Research And Psychology To Elevate Data Storytelling</a>,” Victor Yocco &amp; Angelica Lo Duca</li>
<li>“<a href="https://www.smashingmagazine.com/2025/02/integrations-from-simple-data-transfer-to-composable-architectures/">Integrations: From Simple Data Transfer To Modern Composable Architectures</a>,” Edoardo Dusi</li>
<li>“<a href="https://www.smashingmagazine.com/2024/06/scaling-success-key-insights-pratical-takeaways/">Scaling Success: Key Insights And Practical Takeaways</a>,” Addy Osmani</li>
<li>“<a href="https://www.smashingmagazine.com/2024/09/embracing-introversion-in-ux/">Embracing Introversion In UX</a>,” Victor Yocco</li>
</ul>
<div class="signature">
  <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 />
  <span>(mrn, yk)</span>
</div>
</article>
]]></content:encoded>
					
					<wfw:commentRss>http://computercoursesonline.com/index.php/2025/05/27/data-vs-findings-vs-insights-in-ux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Smashing Animations Part 3: SMIL’s Not Dead Baby, SMIL’s Not Dead</title>
		<link>http://computercoursesonline.com/index.php/2025/05/21/smashing-animations-part-3-smils-not-dead-baby-smils-not-dead/</link>
					<comments>http://computercoursesonline.com/index.php/2025/05/21/smashing-animations-part-3-smils-not-dead-baby-smils-not-dead/#respond</comments>
		
		<dc:creator><![CDATA[.]]></dc:creator>
		<pubDate>Wed, 21 May 2025 08:00:00 +0000</pubDate>
				<category><![CDATA[Css]]></category>
		<guid isPermaLink="false">http://computercoursesonline.com/?p=935</guid>

					<description><![CDATA[Smashing Animations Part 3: SMIL’s Not Dead Baby, SMIL’s Not Dead Smashing Animations Part 3: SMIL’s Not Dead Baby, SMIL’s Not Dead Andy Clarke 2025-05-21T08:00:00+00:00 2025-06-05T21:02:28+00:00 The SMIL specification was introduced by the W3C in 1998 for synchronizing multimedia. This was long before CSS animations or JavaScript-based animation libraries were available. It was built into SVG 1.1, which is why we can still use it there today....]]></description>
										<content:encoded><![CDATA[<p>              <title>Smashing Animations Part 3: SMIL’s Not Dead Baby, SMIL’s Not Dead</title></p>
<article>
<header>
<h1>Smashing Animations Part 3: SMIL’s Not Dead Baby, SMIL’s Not Dead</h1>
<address>Andy Clarke</address>
<p>                  2025-05-21T08:00:00+00:00<br />
                  2025-06-05T21:02:28+00:00<br />
                </header>
<p>The SMIL specification was introduced by the W3C in 1998 for synchronizing multimedia. This was long before CSS animations or JavaScript-based animation libraries were available. It was built into SVG 1.1, which is why we can still use it there today.</p>
<p>Now, you might’ve heard that <a href="https://css-tricks.com/smil-is-dead-long-live-smil-a-guide-to-alternatives-to-smil-features">SMIL is dead</a>. However, it’s alive and well since Google reversed a decision to deprecate the technology almost a decade ago. It remains a terrific choice for designers and developers who want simple, semantic ways to add animations to their designs.</p>
<figure class="
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/1-yogi-bear-show.png"></p>
<p>    <img loading="lazy" width="800" height="540" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="The Yogi Bear Show illustration" 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-3-smil-not-dead/1-yogi-bear-show.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      The Yogi Bear Show © Warner Bros. Entertainment Inc. (<a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/1-yogi-bear-show.png">Large preview</a>)<br />
    </figcaption></figure>
<p><strong>Tip</strong>: <em>There’s now a website where you can see all my <a href="https://stuffandnonsense.co.uk/toon-titles">Toon Titles</a>.</em></p>
<div class="refs">
<ul>
<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>
<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>
</ul>
</div>
<div data-audience="non-subscriber" data-remove="true" class="feature-panel-container">
<aside class="feature-panel">
<div class="feature-panel-left-col">
<div class="feature-panel-description">
<p>Meet <strong><a data-instant href="https://www.smashingconf.com/online-workshops/">Smashing Workshops</a></strong> on <strong>front-end, design &amp; UX</strong>, with practical takeaways, live sessions, <strong>video recordings</strong> and a friendly Q&amp;A. With Brad Frost, Stéph Walter and <a href="https://smashingconf.com/online-workshops/workshops">so many others</a>.</p>
<p><a data-instant href="smashing-workshops" class="btn btn--green btn--large">Jump to the workshops&nbsp;↬</a></div>
</div>
<div class="feature-panel-right-col"><a data-instant href="smashing-workshops" class="feature-panel-image-link"></p>
<div class="feature-panel-image">
<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>
</div>
<p></a>
</div>
</aside>
</div>
<h2 id="introducing-mike-worth">Introducing Mike Worth</h2>
<p>I’ve recently been working on a new website for Emmy-award-winning game composer Mike Worth. He hired me to create a bold, retro-style design that showcases his work. I used animations throughout to delight and surprise his audience as they move through his website.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/2-mike-worth-website.png"></p>
<p>    <img loading="lazy" width="800" height="550" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Illustrations from Mike Worth’s 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-3-smil-not-dead/2-mike-worth-website.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      Design by <a href="https://stuffandnonsense.co.uk/">Andy Clarke, Stuff &amp; Nonsense</a>. Mike Worth’s website will launch in June 2025, but you can see <a href="https://codepen.io/collection/YwMKPb">examples from this article on CodePen</a>. (<a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/2-mike-worth-website.png">Large preview</a>)<br />
    </figcaption></figure>
<p>Mike loves ’90s animation &mdash; especially <a href="https://en.wikipedia.org/wiki/DuckTales_(1987_TV_series)">Disney’s</a> <a href="https://en.wikipedia.org/wiki/DuckTales_(1987_TV_series)"><em>Duck Tales</em></a>. Unsurprisingly, my taste in cartoons stretches back a little further to <a href="https://en.wikipedia.org/wiki/Hanna-Barbera">Hanna-Barbera</a> shows like Dastardly and Muttley in <em>Their Flying Machines</em>, <em>Scooby-Doo</em>, <em>The Perils of Penelope Pitstop</em>, <em>Wacky Races</em>, and, of course, <a href="https://en.wikipedia.org/wiki/Yogi_Bear"><em>The Yogi Bear Show</em></a>. So, to explain how this era of animation relates to SVG, I’ll be adding SMIL animations in SVG to title cards from some classic Yogi Bear cartoons.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/3-yogi-bear-show.png"></p>
<p>    <img loading="lazy" width="800" height="300" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="The Yogi Bear Show illustrations" 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-3-smil-not-dead/3-yogi-bear-show.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      The Yogi Bear Show © Warner Bros. Entertainment Inc. (<a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/3-yogi-bear-show.png">Large preview</a>)<br />
    </figcaption></figure>
<p>Fundamentally, animation changes how an element looks and where it appears over time using a few basic techniques. That might be simply shifting an element up or down, left or right, to create the appearance of motion, like Yogi Bear moving across the screen.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/4-yogi-bear-title-card.png"></p>
<p>    <img loading="lazy" width="800" height="450" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Yogi Bear title card design recreated by Andy Clarke" 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-3-smil-not-dead/4-yogi-bear-title-card.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      Yogi Bear title card design by Lawrence Goble (1958). Author’s recreation. (<a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/4-yogi-bear-title-card.png">Large preview</a>)<br />
    </figcaption></figure>
<p>Rotating objects around a fixed point can create everything, from simple spinning effects to natural-looking movements of totally normal things, like a bear under a parachute falling from the sky.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/5-yogi-bear-title-card-design.png"></p>
<p>    <img loading="lazy" width="800" height="450" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Yogi Bear title card recreated by Andy Clarke" 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-3-smil-not-dead/5-yogi-bear-title-card-design.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      Yogi Bear title card design by Lawrence Goble (1958). Author’s recreation. (<a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/5-yogi-bear-title-card-design.png">Large preview</a>)<br />
    </figcaption></figure>
<p>Scaling makes an element grow, shrink, or stretch, which can add drama, create perspective, or simulate depth.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/6-yogi-bear-title-card.png"></p>
<p>    <img loading="lazy" width="800" height="450" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Yogi Bear title card recreated by Andy Clarke" 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-3-smil-not-dead/6-yogi-bear-title-card.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      Yogi Bear title card design by Lawrence Goble (1958). Author’s recreation. (<a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/6-yogi-bear-title-card.png">Large preview</a>)<br />
    </figcaption></figure>
<p>Changing colour and transitioning opacity can add atmosphere, create a mood, and enhance visual storytelling. Just these basic principles can create animations that attract attention and improve someone’s experience using a design.</p>
<p>These results are all achievable using CSS animations, but some SVG properties can’t be animated using CSS. Luckily, we can do more &mdash; and have much more fun &mdash; using SMIL animations in SVG. We can combine complex animations, move objects along paths, and control when they start, stop, and everything in between.</p>
<p>Animations can be embedded within any SVG element, including <a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorials/SVG_from_scratch/Basic_shapes">primitive shapes</a> like circles, ellipses, and rectangles. They can also be encapsulated into groups, paths, and polygons:</p>
<pre><code class="language-svg">&lt;circle ...&gt;
  &lt;animate&gt;...&lt;/animate&gt;
&lt;/circle&gt;
</code></pre>
<p>Animations can also be defined outside an element, elsewhere in an SVG, and connected to it using an <code>xlink</code> attribute:</p>
<pre><code class="language-svg">&lt;g id="yogi"&gt;...&lt;/g&gt;
  ...
&lt;animate xlink:href="#yogi"&gt;…&lt;/animate&gt;
</code></pre>
<h2 id="building-an-animation">Building An Animation</h2>
<p><code>&lt;animate&gt;</code> is just one of several animation elements in SVG. Together with an <code>attributeName</code> value, it enables animations based on one or more of an element’s attributes.</p>
<p>Most animation explanations start by moving a primitive shape, like this exciting circle:</p>
<pre><code class="language-svg">&lt;circle
  r="50"
  cx="50" 
  cy="50" 
  fill="#062326" 
  opacity="1"
/&gt;
</code></pre>
<p>Using this <code>attributeName</code> property, I can define which of this circle’s attributes I want to animate, which, in this example, is its <code>cx</code> (x-axis center point) position:</p>
<pre><code class="language-svg">&lt;circle ... &gt;
  &lt;animate attributename="cx"&gt;&lt;/animate&gt;
&lt;/circle&gt;
</code></pre>
<p>On its own, this does precisely nothing until I define three more values. The <code>from</code> keyword specifies the circle’s initial position, <code>to</code>, its final position, and the <code>dur</code>-ation between those two positions:</p>
<pre><code class="language-svg">&lt;circle ... &gt;
  &lt;animate 
  attributename="cx"
  from="50" 
  to="500"
  dur="1s"&gt;
  &lt;/animate&gt;
&lt;/circle&gt;
</code></pre>
<p>If I want more precise control, I can replace <code>from</code> and <code>to</code> with a set of <code>values</code> separated by semicolons:</p>
<pre><code class="language-svg">&lt;circle ... &gt;
  &lt;animate 
  attributename="cx"
  values="50; 250; 500; 250;"
  dur="1s"&gt;
  &lt;/animate&gt;
&lt;/circle&gt;
</code></pre>
<p>Finally, I can define how many times the animation repeats (<code>repeatcount</code>) and even after what period that repeating should stop (<code>repeatdur</code>):</p>
<pre><code class="language-svg">&lt;circle ... &gt;
  &lt;animate 
  attributename="cx"
  values="50; 250; 500; 250;"
  dur="1s"
  repeatcount="indefinite"
  repeatdur="180s"&gt;
&lt;/circle&gt;
</code></pre>
<p>Most SVG elements have attributes that can be animated. This title card from 1959’s <a href="https://yogibear.fandom.com/wiki/Brainy_Bear">“Brainy Bear” episode</a> shows Yogi in a crazy scientist‘s brain experiment. Yogi’s head is under the dome, and energy radiates around him.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/7-yogi-bear-show.png"></p>
<p>    <img loading="lazy" width="800" height="540" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="The Yogi Bear Show illustration where Yogi’s head is under the dome, and energy radiates around him" 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-3-smil-not-dead/7-yogi-bear-show.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      The Yogi Bear Show © Warner Bros. Entertainment Inc. (<a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/7-yogi-bear-show.png">Large preview</a>)<br />
    </figcaption></figure>
<p>To create the buzz around Yogi, my SVG includes three <code>path</code> elements, each with <code>opacity</code>, <code>stroke</code>, and <code>stroke-width</code> attributes, which can all be animated:</p>
<pre><code class="language-svg">&lt;path opacity="1" stroke="#fff" stroke-width="5" ... /&gt;
</code></pre>
<p>I animated each path’s <code>opacity</code>, changing its value from <code>1</code> to <code>.5</code> and back again:</p>
<pre><code class="language-svg">&lt;path opacity="1" ... &gt;
  &lt;animate 
    attributename="opacity"
    values="1; .25; 1;"
    dur="1s"
    repeatcount="indefinite"&gt;
  &lt;/animate&gt;
&lt;/path&gt;
</code></pre>
<p>Then, to radiate energy from Yogi, I specified when each animation should <code>begin</code>, using a different value for each <code>path</code>:</p>
<pre><code class="language-svg">&lt;path ... &gt;
  &lt;animate begin="0" … &gt;
&lt;/path&gt;

&lt;path ... &gt;
  &lt;animate begin=".5s" … &gt;
&lt;/path&gt;

&lt;path ... &gt;
  &lt;animate begin="1s" … &gt;
&lt;/path&gt;
</code></pre>
<p>I’ll explain more about the <code>begin</code> property and how to start animations after this short commercial break.</p>
<p>Try this yourself:</p>
<figure class="break-out">
<p data-height="480" data-theme-id="light" data-slug-hash="qEEzYgG" data-user="smashingmag" data-default-tab="result" class="codepen">See the Pen [Brainy Bear SVG animation [forked]](https://codepen.io/smashingmag/pen/qEEzYgG) by <a href="https://codepen.io/malarkey">Andy Clarke</a>.</p><figcaption>See the Pen <a href="https://codepen.io/smashingmag/pen/qEEzYgG">Brainy Bear SVG animation [forked]</a> by <a href="https://codepen.io/malarkey">Andy Clarke</a>.</figcaption></figure>
<p>To make animations appear more natural, I can apply more than one <code>animate</code> element and give each one a different <code>attributename</code> value. Those paths also contain a <code>stroke-width</code> attribute, which I can also animate by changing the stroke widths between <code>5</code> and <code>7</code>:</p>
<pre><code class="language-svg">&lt;path ... &gt;
  &lt;animate attributename="opacity" ... &gt;&lt;/animate&gt;
  &lt;animate attributename="stroke-width" ... &gt;&lt;/animate&gt;
&lt;/path&gt;
</code></pre>
<p>Finally, I can animate the dome over Yogi’s head, changing its <code>fill</code> colour between two values over five seconds to create the impression that the crazy scientist’s machine is heating up:</p>
<pre><code class="language-svg">&lt;path fill="#50D9E0" ... &gt;
  &lt;animate
    attributename="fill"
    values="#50D9E0; #E18C50;"
    dur="5s"
    begin="2s"
  &gt;
&lt;/path&gt;
</code></pre>
<p>Implement that code, and you’ll soon notice that the dome returns to its original state after the animation is complete. To retain its colour at the end of the animation, I can add the &mdash; confusingly named &mdash; <code>fill</code> property and a value of <code>freeze.</code> This stops the animation in its final state and prevents it from returning to the original colour:</p>
<pre><code class="language-svg">&lt;path fill="#50D9E0" ... &gt;
  &lt;animate fill="freeze"&gt;
&lt;/path&gt;
</code></pre>
<p>Animating attributes brings these title card designs to life, whether by adjusting the position of a primitive shape, its opacity, and stroke width or by creating complex sequences with staggered timing. But there’s still more I can do, starting with the next animation element, <code>animateTransform</code>.</p>
<div class="partners__lead-place"></div>
<h2 id="animatetransform"><code>animateTransform</code></h2>
<p>If <code>&lt;animate&gt;</code> controls attributes, then <code>animateTransform</code> animates transformations, including rotations, scaling, skewing, and translations. It works by changing the values of a transform property, like this <code>translate</code>:</p>
<pre><code class="language-svg">&lt;path transform="translate(0,0)"/&gt;
</code></pre>
<p>Then, the animation works the same way as <code>&lt;animate&gt;</code>, adding an <code>attributename</code> and specifying the type of transform, in this example, <code>rotate:</code></p>
<pre><code class="language-svg">&lt;animatetransform 
  attributename="transform"
  type="rotate"&gt;
&lt;/animatetransform&gt;
</code></pre>
<p>I can use either <code>from</code> and <code>to</code> or the <code>values</code> attribute to define how an element is transformed.</p>
<ul>
<li><strong>Scale</strong> uses <code>x</code> and <code>y</code> values  (<code>.5</code>, <code>1</code>).</li>
<li><strong>Rotate</strong> uses degrees (<code>0</code>–<code>360</code>) plus optional <code>x</code> and <code>y</code> (<code>360</code>, <code>0</code>, <code>0</code>).</li>
<li><strong>Translate</strong> also uses <code>x</code> and <code>y</code> values  (<code>50</code>, <code>100</code>).</li>
<li><strong>Skew</strong> uses <code>x</code> and <code>y</code> values, too (<code>50</code>, <code>100</code>).</li>
</ul>
<p>What’s interesting about those values is that they can be added to an element’s existing values instead of replacing them. For example, when an attribute contains a <code>translate</code> value of <code>100, 0</code>:</p>
<pre><code class="language-svg">&lt;path transform="translate(100, 0)"/&gt;
</code></pre>
<p>And then I animate that translation horizontally by <code>100</code>:</p>
<pre><code class="language-svg">&lt;animatetransform
  attributename="transform"
  type="translate"
  from="0, 0"
  to="100, 0"
  additive="sum"&gt;
&lt;/animatetransform&gt;
</code></pre>
<p>Using the <code>additive</code> property with a value of <code>sum</code>, the animation values are relative to the original, starting the animation at <code>100</code> and ending at <code>200</code> by adding <code>100</code> to <code>100</code>.</p>
<p>Similarly, if I give the <code>accumulate</code> property a value of <code>sum</code>, each instance of animation will build on the last. So, in an animation where an element is translated by <code>100</code> and repeats five times, each movement will be cumulative, moving the element by <code>500</code>:</p>
<pre><code class="language-svg">&lt;animatetransform
  attributename="transform"
  type="translate"
  from="0, 0"
  to="100, 0"
  additive="sum"
  accumulate="sum" 
/&gt;
</code></pre>
<p>This title card from 1958’s Yogi Bear’s <a href="https://yogibear.fandom.com/wiki/Yogi_Bear%27s_Big_Break">“Big Break” episode</a> shows Yogi floating from the sky under a parachute.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/8-yogi-bear-show.png"></p>
<p>    <img loading="lazy" width="800" height="540" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="The Yogi Bear Show illustration shows Yogi floating from the sky under a parachute" 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-3-smil-not-dead/8-yogi-bear-show.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      The Yogi Bear Show © Warner Bros. Entertainment Inc. (<a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/8-yogi-bear-show.png">Large preview</a>)<br />
    </figcaption></figure>
<p>I needed two types of transform animations to generate the effect of Yogi drifting gently downwards: <code>translate</code>, and <code>rotate</code>. I first added an <code>animatetransform</code> element to the group, which contains Yogi and his chute. I defined his initial vertical position &mdash; <code>1200</code> off the top of the <code>viewBox</code> &mdash; then translated his descent to <code>1000</code> over a 15-second duration:</p>
<pre><code class="language-svg">&lt;g transform="translate(1200, -1200)"&gt;
  ...
  &lt;animateTransform
    attributeName="transform"
    type="translate"
    values="500,-1200; 500,1000"
    dur="15s"
    repeatCount="1" 
  /&gt;
&lt;/g&gt;
</code></pre>
<p>Yogi appears to fall from the sky, but the movement looks unrealistic. So, I added a second <code>animatetransform</code> element, this time with an indefinitely repeating +/- 5-degree rotation to swing Yogi from side to side during his descent:</p>
<pre><code class="language-svg">&lt;animateTransform
  attributeName="transform"
  type="rotate"
  values="-5; 5; -5"
  dur="14s"
  repeatCount="indefinite"
  additive="sum" 
/&gt;
</code></pre>
<p>Try this yourself:</p>
<figure class="break-out">
<p data-height="480" data-theme-id="light" data-slug-hash="PwwraNm" data-user="smashingmag" data-default-tab="result" class="codepen">See the Pen [Big Break SVG animation [forked]](https://codepen.io/smashingmag/pen/PwwraNm) by <a href="https://codepen.io/malarkey">Andy Clarke</a>.</p><figcaption>See the Pen <a href="https://codepen.io/smashingmag/pen/PwwraNm">Big Break SVG animation [forked]</a> by <a href="https://codepen.io/malarkey">Andy Clarke</a>.</figcaption></figure>
<h2 id="starting-and-stopping">Starting And Stopping</h2>
<p>So far, every animation begins as soon as the page has loaded. But there are ways to not only delay the start of animation but define precisely where it begins, using the begin <code>property</code>:</p>
<p>In this title card from 1959’s <a href="https://yogibear.fandom.com/wiki/Robin_Hood_Yogi">“Robin Hood Yogi”</a>, Yogi shoots an arrow into an apple on Boo-Boo’s head.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/9-yogi-bear-show.png"></p>
<p>    <img loading="lazy" width="800" height="540" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="The Yogi Bear Show illustration where Yogi shoots an arrow into an apple on Boo-Boo’s head" 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-3-smil-not-dead/9-yogi-bear-show.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      The Yogi Bear Show © Warner Bros. Entertainment Inc. (<a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/9-yogi-bear-show.png">Large preview</a>)<br />
    </figcaption></figure>
<p>By default, the arrow is set loose when the page loads. Blink, and you might miss it. To build some anticipation, I can <code>begin</code> the animation two seconds later:</p>
<pre><code class="language-svg">&lt;animatetransform
  attributename="transform"
  type="translate"
  from="0 0"
  to="750 0"
  dur=".25s"
  begin="2s"
  fill="freeze"
/&gt;
</code></pre>
<p>Or, I can let the viewer take the shot when they click the arrow:</p>
<pre><code class="language-svg">&lt;animatetransform
  ...
  begin="click"
/&gt;
</code></pre>
<p>And I can combine the click event and a delay, all with no JavaScript, just a smattering of SMIL:</p>
<pre><code class="language-svg">&lt;animatetransform
  ...
  begin="click + .5s"
/&gt;
</code></pre>
<p>Try this yourself by clicking the arrow:</p>
<figure class="break-out">
<p data-height="480" data-theme-id="light" data-slug-hash="OPPeERj" data-user="smashingmag" data-default-tab="result" class="codepen">See the Pen [Robin Hood Yogi CSS animation [forked]](https://codepen.io/smashingmag/pen/OPPeERj) by <a href="https://codepen.io/malarkey">Andy Clarke</a>.</p><figcaption>See the Pen <a href="https://codepen.io/smashingmag/pen/OPPeERj">Robin Hood Yogi CSS animation [forked]</a> by <a href="https://codepen.io/malarkey">Andy Clarke</a>.</figcaption></figure>
<h2 id="synchronising-animations">Synchronising Animations</h2>
<p>In his 1958 <a href="https://yogibear.fandom.com/wiki/Pie-Pirates">“Pie-Pirates” episode</a>, Yogi Bear tries to steal a pie and has to outwit a bulldog. The title card &mdash; designed by Lawrence Goble &mdash; shows the chase but, alas, (spoiler alert) no stolen pie.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/10-yogi-bear-show.png"></p>
<p>    <img loading="lazy" width="800" height="540" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="The Yogi Bear Show illustration showing a bulldog chasing 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-3-smil-not-dead/10-yogi-bear-show.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      The Yogi Bear Show © Warner Bros. Entertainment Inc. (<a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/10-yogi-bear-show.png">Large preview</a>)<br />
    </figcaption></figure>
<p>To bring this title card to life, I needed two groups of paths: one for Yogi and the other for the dog. I translated them both off the left edge of the <code>viewBox</code>:</p>
<pre><code class="language-svg">&lt;g class="dog" transform="translate(-1000, 0)"&gt;
  ...
&lt;/g&gt;

&lt;g class="yogi" transform="translate(-1000, 0)"&gt;
  ...
&lt;/g&gt;
</code></pre>
<p>Then, I applied an <code>animatetransform</code> element to both groups, which moves them back into view:</p>
<pre><code class="language-svg">&lt;!-- yogi --&gt;
&lt;animateTransform
  attributeName="transform"
  type="translate"
  from="-1000,0"
  to="0,0"
  dur="2s"
  fill="freeze"
/&gt;

&lt;!-- dog --&gt;
&lt;animateTransform
  attributeName="transform"
  type="translate"
  from="-1000,0"
  to="0,0"
  dur=".5s"
  fill="freeze"
/&gt;
</code></pre>
<p>This sets up the action, but the effect feels flat, so I added another pair of animations that bounce both characters:</p>
<pre><code class="language-svg">&lt;!-- yogi --&gt;
&lt;animateTransform
  attributeName="transform"
  type="rotate"
  values="-1,0,450; 1,0,450; -1,0,450"
  dur=".25s"
  repeatCount="indefinite"
/&gt;

&lt;!-- dog --&gt;
&lt;animateTransform
  attributeName="transform"
  type="rotate"
  values="-1,0,450; 1,0,450; -1,0,450"
  dur="0.5s"
  repeatCount="indefinite"
/&gt;
</code></pre>
<p>Animations can begin when a page loads, after a specified time, or when clicked. And by naming them, they can also synchronise with other animations.</p>
<p>I wanted Yogi to enter the frame first to build anticipation, with a short pause before other animations begin, synchronising to the moment he’s arrived. First, I added an ID to Yogi’s <code>translate</code> animation:</p>
<pre><code class="language-svg">&lt;animateTransform
  id="yogi"
  type="translate"
  ...
/&gt;
</code></pre>
<blockquote><p><strong>Watch out</strong>: For a reason, I can’t, for the life of me, explain why Firefox won’t begin animations with an ID when the ID contains a hyphen. This isn’t smarter than the average browser, but replacing hyphens with underscores fixes the problem.</p></blockquote>
<p>Then, I applied a <code>begin</code> to his <code>rotate</code> animation, which starts playing a half-second after the <code>#yogi</code> animation ends:</p>
<pre><code class="language-svg">&lt;animateTransform
  type="rotate"
  begin="yogi.end + .5s"
  ...
/&gt;
</code></pre>
<p>I can build sophisticated sets of synchronised animations using the <code>begin</code> property and whether a named animation begins or ends. The bulldog chasing Yogi enters the frame two seconds after Yogi begins his entrance:</p>
<pre><code class="language-svg">&lt;animateTransform
  id="dog"
  type="translate"
  begin="yogi.begin + 2s"
  fill="freeze"
  ...
/&gt;
</code></pre>
<p>One second after the dog has caught up with Yogi, a <code>rotate</code> transformation makes him bounce, too:</p>
<pre><code class="language-svg">&lt;animateTransform
  type="rotate"
  ...
  begin="dog.begin + 1s"
  repeatCount="indefinite" 
/&gt;
</code></pre>
<p>The background rectangles whizzing past are also synchronised, this time to one second before the bulldog ends his run:</p>
<pre><code class="language-svg">&lt;rect ...&gt;
  &lt;animateTransform
    begin="dog.end + -1s"
  /&gt;
&lt;/rect&gt;
</code></pre>
<p>Try this yourself:</p>
<figure class="break-out">
<p data-height="480" data-theme-id="light" data-slug-hash="LEEKryp" data-user="smashingmag" data-default-tab="result" class="codepen">See the Pen [Pie-Pirates SVG animation [forked]](https://codepen.io/smashingmag/pen/LEEKryp) by <a href="https://codepen.io/malarkey">Andy Clarke</a>.</p><figcaption>See the Pen <a href="https://codepen.io/smashingmag/pen/LEEKryp">Pie-Pirates SVG animation [forked]</a> by <a href="https://codepen.io/malarkey">Andy Clarke</a>.</figcaption></figure>
<p>The timing of this background movement is synchronised with the dog arriving, which, in turn, is relative to Yogi’s arrival, building a sequence of animations that all feel connected.</p>
<div class="partners__lead-place"></div>
<h2 id="animating-along-motion-paths">Animating Along Motion Paths</h2>
<p>Until now, all the animations in these title cards have been up, down, left, right, or one combination or another. But there’s one more aspect of SMIL in SVG, which can add an extra dimension to animations: animating along motion paths using the <code>animatemotion</code> element.</p>
<p><code>animatemotion</code> accepts all the same properties and values as <code>animate</code> and <code>animateTransform</code>, but adds a few more for finer control over direction and timing. <code>animatemotion</code> uses the <code>path</code> property to enable elements to move along a motion path. It also uses the <code>d</code> value for coordinate data in the same way as any conventional path.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/11-yogi-bear-show.png"></p>
<p>    <img loading="lazy" width="800" height="540" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="The Yogi Bear Show illustration of the Runaway 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-3-smil-not-dead/11-yogi-bear-show.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      The Yogi Bear Show © Warner Bros. Entertainment Inc. (<a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/11-yogi-bear-show.png">Large preview</a>)<br />
    </figcaption></figure>
<p>In <a href="https://yogibear.fandom.com/wiki/The_Runaway_Bear">“The Runaway Bear”</a> from 1959, Yogi must avoid a hunter turning his head into a trophy. I wanted Yogi to leap in and out of the screen by making him follow a path. I also wanted to vary the speed of his dash: speeding up as he enters and exits, and slowing down as he passes the title text.</p>
<p>I first added a <code>path</code> property, using its coordinate data to give Yogi a route to follow, and specified a two-second duration for my animation:</p>
<pre><code class="language-svg">&lt;g&gt;
  &lt;animateMotion
    dur="2s"
    path="..."
  &gt;
  &lt;/animateMotion&gt;
&lt;/g&gt;
</code></pre>
<p>Alternatively, I could add a <code>path</code> element, leave it visible, or prevent it from being rendered by placing it inside a <code>defs</code> element:</p>
<pre><code class="language-svg">&lt;defs&gt;
  &lt;path id="yogi" d="..." /&gt;
&lt;/defs&gt;
</code></pre>
<p>I can then reference that by using a <code>mpath</code> element inside my <code>animateMotion</code>:</p>
<pre><code class="language-svg">&lt;animateMotion
  ...
  &lt;mpath href="#yogi" /&gt;
&lt;/animateMotion&gt;
</code></pre>
<p>I experimented with several paths before settling on the one that delivered the movement shape I was looking for:</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/12-yogi-bear-title-card-recreations.png"></p>
<p>    <img loading="lazy" width="800" height="450" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Several variants of the Yogi Bear title card recreated by Andy Clarke" 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-3-smil-not-dead/12-yogi-bear-title-card-recreations.png"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      Yogi Bear title card design by Lawrence Goble (1959.) Author’s recreation. (<a href="https://files.smashing.media/articles/smashing-animations-part-3-smil-not-dead/12-yogi-bear-title-card-recreations.png">Large preview</a>)<br />
    </figcaption></figure>
<p>One was too bouncy, one was too flat, but the third motion path was just right. Almost, as I also wanted to vary the speed of Yogi’s dash: speeding him up as he enters and exits and slowing him down as he passes the title text.</p>
<p>The <code>keyPoints</code> property enabled me to specify points along the motion path and then adjust the duration Yogi spends between them. To keep things simple, I defined five points between <code>0</code> and <code>1</code>:</p>
<pre><code class="language-svg">&lt;animateMotion
  ...
  keyPoints="0; .35; .5; .65; 1;"
&gt;
&lt;/animateMotion&gt;
</code></pre>
<p>Then I added the same number of <code>keyTimes</code> values, separated by semicolons, to control the pacing of this animation:</p>
<pre><code class="language-svg">&lt;animateMotion
  ...
  keyTimes="0; .1; .5; .95; 1;"
&gt;
&lt;/animateMotion&gt;
</code></pre>
<p>Now, Yogi rushes through the first three <code>keyPoints</code>, slows down as he passes the title text, then speeds up again as he exits the <code>viewBox</code>.</p>
<p>Try this yourself:</p>
<figure class="break-out">
<p data-height="480" data-theme-id="light" data-slug-hash="oggryox" data-user="smashingmag" data-default-tab="result" class="codepen">See the Pen [Runaway Bear SVG animation [forked]](https://codepen.io/smashingmag/pen/oggryox) by <a href="https://codepen.io/malarkey">Andy Clarke</a>.</p><figcaption>See the Pen <a href="https://codepen.io/smashingmag/pen/oggryox">Runaway Bear SVG animation [forked]</a> by <a href="https://codepen.io/malarkey">Andy Clarke</a>.</figcaption></figure>
<h2 id="smil-s-not-dead-baby-smil-s-not-dead">SMIL’s Not Dead, Baby. SMIL’s Not Dead</h2>
<p>With their ability to control transformations, animate complex motion paths, and synchronise multiple animations, SMIL animations in SVG are still powerful tools. They can bring design to life without needing a framework or relying on JavaScript. It’s compact, which makes it great for small SVG effects.</p>
<p>SMIL includes the <code>begin</code> attribute, which makes chaining animations far more intuitive than with CSS. Plus, SMIL lives inside the SVG file, making it perfect for animations that travel with an asset. So, while SMIL is not modern by today’s standards and may be a little bit niche, it can still be magical.</p>
<blockquote class="pull-quote">
<p>
    <a class="pull-quote__link" aria-label="Share on Twitter" href="https://twitter.com/share?text=%0aDon%e2%80%99t%20let%20the%20misconception%20that%20SMIL%20is%20%e2%80%9cdead%e2%80%9d%20stop%20you%20from%20using%20this%20fantastic%20tool.%0a&amp;url=https://smashingmagazine.com%2f2025%2f05%2fsmashing-animations-part-3-smil-not-dead%2f"></p>
<p>Don’t let the misconception that SMIL is “dead” stop you from using this fantastic tool.</p>
<p>    </a>
  </p>
<div class="pull-quote__quotation">
<div class="pull-quote__bg">
      <span class="pull-quote__symbol">“</span></div>
</p></div>
</blockquote>
<p>Google reversed its decision to deprecate SMIL almost a decade ago, so it remains a terrific choice for designers and developers who want <strong>simple</strong>, <strong>semantic ways</strong> to add animations to their designs.</p>
<div class="signature">
  <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 />
  <span>(yk)</span>
</div>
</article>
]]></content:encoded>
					
					<wfw:commentRss>http://computercoursesonline.com/index.php/2025/05/21/smashing-animations-part-3-smils-not-dead-baby-smils-not-dead/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Design System In 90 Days</title>
		<link>http://computercoursesonline.com/index.php/2025/05/19/design-system-in-90-days/</link>
					<comments>http://computercoursesonline.com/index.php/2025/05/19/design-system-in-90-days/#respond</comments>
		
		<dc:creator><![CDATA[.]]></dc:creator>
		<pubDate>Mon, 19 May 2025 10:00:00 +0000</pubDate>
				<category><![CDATA[Ux]]></category>
		<guid isPermaLink="false">http://computercoursesonline.com/?p=919</guid>

					<description><![CDATA[Design System In 90 Days Design System In 90 Days Vitaly Friedman 2025-05-19T10:00:00+00:00 2025-05-22T21:02:44+00:00 So we want to set up a new design system for your product. How do we get it up and running from scratch? Do we start with key stakeholders, UI audits, or naming conventions? And what are some of the critical...]]></description>
										<content:encoded><![CDATA[<p>              <title>Design System In 90 Days</title></p>
<article>
<header>
<h1>Design System In 90 Days</h1>
<address>Vitaly Friedman</address>
<p>                  2025-05-19T10:00:00+00:00<br />
                  2025-05-22T21:02:44+00:00<br />
                </header>
<p>So we want to set up a new design system for your product. How do we get it up and running from scratch? Do we start with key stakeholders, UI audits, or naming conventions? And what are some of the <strong>critical conversations</strong> we need to have early to avoid problems down the line?</p>
<p>Fortunately, there are a few <strong>useful little helpers</strong> to get started &mdash; and they are the ones I tend to rely on quite a bit when initiating any design system projects.</p>
<h2 id="design-system-in-90-days-canvas">Design System In 90 Days Canvas</h2>
<p><a href="https://www.figma.com/community/file/1275210165201477676"><strong>Design System in 90 Days Canvas (FigJam template)</strong></a> is a handy set of <strong>useful questions</strong> to start a design system effort. Essentially, it’s a roadmap to discuss everything from the value of a design system to stakeholders, teams involved, and components to start with.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://www.figma.com/community/file/1275210165201477676/design-system-in-90-days-canvas"></p>
<p>    <img loading="lazy" width="800" height="1002" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Design System in 90 Days Canvas" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/mailing-91-design-system-90-days/1-mailing-91-design-system-90-days.jpg"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      Very comprehensive and helpful: <a href="https://www.figma.com/community/file/1275210165201477676/design-system-in-90-days-canvas">Design System in 90 Days Canvas</a> by Dan Mall.<br />
    </figcaption></figure>
<p>A neat little helper to get a design system up and running &mdash; and adopted! &mdash; in 90 days. Created for small and large companies that are building a design system or plan to set up one. Kindly shared by Dan Mall.</p>
<h2 id="practical-design-system-tactics">Practical Design System Tactics</h2>
<p><a href="https://redesigningdesign.systems/tactics/all-tactics"><strong>Design System Tactics</strong></a> is a practical overview of tactics to help designers <strong>make progress with a design system at every stage</strong> &mdash; from crafting system principles to component discovery to design system office hours to cross-brand consolidation. Wonderful work by the one-and-only Ness Grixti.</p>
<figure class="
  
    break-out article__image
  
  
  "></p>
<p>    <a href="https://redesigningdesign.systems/tactics/all-tactics"></p>
<p>    <img loading="lazy" width="800" height="968" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="An overview of practical design system tactics displayed as cards" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/mailing-91-design-system-90-days/2-mailing-91-design-system-90-days.jpg"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      <a href="https://redesigningdesign.systems/tactics/all-tactics">Design System Tactics</a>, a practical overview by Ness Grixti.<br />
    </figcaption></figure>
<h2 id="design-system-worksheet-pdf">Design System Worksheet (PDF)</h2>
<p><a href="https://medium.com/eightshapes-llc/picking-parts-products-people-a06721e81742"><strong>Design System Checklist</strong></a> by Nathan Curtis (<a href="https://drive.google.com/file/d/1qXMUXKHaEXnLDOu99GCzTMY2XW6NnPe_/view">download the PDF</a>) is a <strong>practical 2-page worksheet</strong> for a 60-minute team activity, designed to choose the right parts, products, and people for your design system.</p>
<figure class="
  
  
  "></p>
<p>    <a href="https://medium.com/eightshapes-llc/picking-parts-products-people-a06721e81742"></p>
<p>    <img loading="lazy" width="800" height="1011" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Design System Parts Worksheet" class="lazyload" data-src="https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_80/w_400/https://files.smashing.media/articles/mailing-91-design-system-90-days/3-mailing-91-design-system-90-days.jpg"></p>
<p>    </a><figcaption class="op-vertical-bottom">
      <a href="https://medium.com/eightshapes-llc/picking-parts-products-people-a06721e81742">Design System Worksheet</a>, by Nathan Curtis.<br />
    </figcaption></figure>
<p>Of course, the point of a design system is not to be fully comprehensive or cover every possible component you might ever need. It’s all about <strong>being useful enough</strong> to help designers produce quality work faster and being flexible enough to help designers make decisions rather than make decisions for them.</p>
<h2 id="useful-questions-to-get-started-with">Useful Questions To Get Started With</h2>
<p>The value of a design system lies in it <strong>being useful and applicable</strong> &mdash; for a large group of people in the organization. And <a href="https://www.linkedin.com/pulse/26-design-system-questions-answer-design-system-university/">according to Dan</a>, a good start is to identify where exactly that value would be most helpful to tackle the company’s <strong>critical challenges and goals</strong>:</p>
<ol>
<li>What is <strong>important to our organization</strong> at the highest level?</li>
<li>Who is important to our design system effort?</li>
<li>What unofficial systems already exist in design and code?</li>
<li>Which teams have <strong>upcoming needs</strong> that a system could solve?</li>
<li>Which teams have <strong>immediate needs</strong> that can grow our system?</li>
<li>Which teams should we and have we talked to?</li>
<li>Which <strong>stakeholders</strong> should we and have we talked to?</li>
<li>What <strong>needs, desires, and concerns</strong> do our stakeholders have?</li>
<li>What components do product or feature teams need now or soon?</li>
<li>What <strong>end-user problems/opportunities</strong> could a system address?</li>
<li>What did we learn about using other design systems?</li>
<li>What is our <strong>repeatable process</strong> for working on products?</li>
<li>What components will we start with?</li>
<li>What needs, desires, and concerns do our stakeholders share?</li>
<li>Where are <strong>our components</strong> currently being used or planned for?</li>
</ol>
<h2 id="useful-resources">Useful Resources</h2>
<p>Here are a few other useful little helpers that might help you in your design system efforts:</p>
<ul>
<li><a href="https://www.linkedin.com/pulse/26-design-system-questions-answer-design-system-university/">Design System Questions To Answer In First 90 Days</a>, by Dan Mall</li>
<li><a href="https://designsystemcanvas.com/">Design System Canvas (PDF / Figjam)</a>, by Paavan Buddhdev</li>
<li><a href="https://www.figma.com/community/file/1360306476090347707/leands-framework">LeanDS Framework (Figma)</a>, by Marianne Ashton-Booth</li>
<li><a href="https://www.linkedin.com/posts/vitalyfriedman_ux-design-figma-activity-7262738783358304257-uooc/">Useful UX Templates For Designers (Figma Kits)</a>, by yours truly, Vitaly Friedman</li>
<li><a href="https://thedesignsystem.guide/">Design System Guide</a>, by Romina Kavcic</li>
</ul>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>A canvas often acts as a <strong>great conversation starter</strong>. It’s rarely complete, but it brings up topics and issues that one wouldn’t have discovered on the spot. We won’t have answers to all questions right away, but we can start <strong>moving in the right direction</strong> to turn a design system effort into a success.</p>
<p>Happy crossing off the right tick boxes!</p>
<h2 id="how-to-measure-ux-and-design-impact">How To Measure UX And Design Impact</h2>
<p>Meet <a href="https://measure-ux.com/">Measure UX &amp; Design Impact</a> (8h), a <strong>practical guide for designers and UX leads</strong> to shape, measure, and explain your incredible UX impact on business. Recorded and updated by Vitaly Friedman. Use the friendly code <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f39f.png" alt="🎟" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong><code>IMPACT</code></strong> to <strong>save 20% off</strong> today. <a href="https://measure-ux.com">Jump to the details</a>.</p>
<figure style="margin-bottom:0;padding-bottom:0" class="break-out article__image">
    <a href="https://measure-ux.com/" title="How To Measure UX and Design Impact, with Vitaly Friedman"><br />
    <img loading="lazy" width="900" height="466" style="border-radius: 11px" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="How to Measure UX and Design Impact, with Vitaly Friedman." class="lazyload" data-src="http://www.computercoursesonline.com/wp-content/uploads/2025/04/measure-ux-and-design-impact-course.png"><br />
    </a><br />
</figure>
<div class="book-cta__inverted">
<div class="book-cta" data-handler="ContentTabs" data-mq="(max-width: 480px)">
<nav class="content-tabs content-tabs--books">
<ul>
<li class="content-tab"><a href="#"><button class="btn btn--small btn--white btn--white--bordered"><br />
Video + UX Training</button></a></li>
<li class="content-tab"><a href="#"><button class="btn btn--small btn--white btn--white--bordered">Video only</button></a></li>
</ul>
</nav>
<div class="book-cta__col book-cta__hardcover content-tab--content">
<h3 class="book-cta__title"><span>Video + UX Training</span></h3>
<p><span class="book-cta__price"><span><span class=""><span class="currency-sign">$</span>&nbsp;<span>495<span class="sup">.00</span></span></span> <span class="book-cta__price--old"><span class="currency-sign">$</span>&nbsp;<span>799<span class="sup">.00</span></span></span></span></span><br />
<a href="https://smart-interface-design-patterns.thinkific.com/enroll/3081832?price_id=3951439" class="btn btn--full btn--medium btn--text-shadow"><br />
Get Video + UX Training</p>
<div></div>
<p></a></p>
<p class="book-cta__desc">25 video lessons (8h) + <a href="https://smashingconf.com/online-workshops/workshops/vitaly-friedman-impact-design/">Live UX Training</a>.<br />100 days money-back-guarantee.</p>
</div>
<div class="book-cta__col book-cta__ebook content-tab--content">
<h3 class="book-cta__title"><span>Video only</span></h3>
<div data-audience="anonymous free supporter" data-remove="true"><span class="book-cta__price" data-handler="PriceTag"><span><span class=""><span class="currency-sign">$</span>&nbsp;<span>250<span class="sup">.00</span></span></span><span class="book-cta__price--old"><span class="currency-sign">$</span>&nbsp;<span>395<span class="sup">.00</span></span></span></span></span></div>
<p><a href="https://smart-interface-design-patterns.thinkific.com/enroll/3081832?price_id=3950630" class="btn btn--full btn--medium btn--text-shadow"><br />
Get the video course</p>
<div></div>
<p></a></p>
<p class="book-cta__desc" data-audience="anonymous free supporter" data-remove="true">25 video lessons (8h). Updated yearly.<br />Also available as a <a href="https://smart-interface-design-patterns.thinkific.com/enroll/3082557?price_id=3951421">UX Bundle with 2 video courses.</a></p>
</div>
<p><span></span></div>
</div>
<h3 id="further-reading-on-smashing-magazine">Further Reading on Smashing Magazine</h3>
<ul>
<li>“<a href="https://www.smashingmagazine.com/2024/07/build-design-systems-penpot-components/">Build Design Systems With Penpot Components</a>,” Mikołaj Dobrucki</li>
<li>“<a href="https://www.smashingmagazine.com/2025/04/anima-playground-figma-designs-live-apps/">How To Turn Your Figma Designs Into Live Apps With Anima Playground</a>,” Anima Team</li>
<li>“<a href="https://www.smashingmagazine.com/2025/04/ux-design-files-organization-template/">UX And Design Files Organization Template</a>,” Vitaly Friedman</li>
<li>“<a href="https://www.smashingmagazine.com/2025/01/digital-playbook-crucial-counterpart-design-system/">The Digital Playbook: A Crucial Counterpart To Your Design System</a>,” Paul Boag</li>
</ul>
<div class="signature">
  <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 />
  <span>(mrn, yk)</span>
</div>
</article>
]]></content:encoded>
					
					<wfw:commentRss>http://computercoursesonline.com/index.php/2025/05/19/design-system-in-90-days/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
