<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Always Twisted| Articles</title>
  <subtitle>A feed of the latest articless from our blog.</subtitle>
  <link href="https://www.alwaystwisted.com/feed.xml" rel="self"/>
  <link href="https://www.alwaystwisted.com/"/>
  <updated>2026-03-04T00:00:00Z</updated>
  <id>https://www.alwaystwisted.com</id>
  <author>
    <name>Stu Robson</name>
    <email>hi@sturobson.com</email>
  </author>
  
    
    <entry>
      <title>Beyond The Blur: A Quick Guide to the CSS Backdrop-Filter Property</title>
      <link href="https://www.alwaystwisted.com/articles/beyond-the-blur-css-backdrop-filter.html"/>
      <updated>2026-03-04T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/beyond-the-blur-css-backdrop-filter.html</id>
      <content type="html">
        <![CDATA[
        <p>Back in 2019 I spotted a post from a Mozilla social media account announcing that <code>backdrop-filter</code> was implemented behind a flag in their Firefox Nightly build. I quickly threw together a <a href="https://codepen.io/sturobson/pen/eYOJMgN/e5979299c33348c312a4320c0f55d3dc">rough demo</a> and then a basic playground to explore what was possible.</p>
<p>Time passed and this last 6 months or so, with broader browser support and real-world usage in client projects, I've finally updated <a href="https://codepen.io/sturobson/pen/raMxdQz">that playground</a> to remove jQuery and modernise the code.</p>
<p>This quick article documents what <code>backdrop-filter</code> is, how it works, and how to use it effectively.</p>
<h2 id="what-is-backdrop-filter%3F" tabindex="-1">What is backdrop-filter?</h2>
<p>The <code>backdrop-filter</code> CSS property applies graphical effects such as blurring or colour shifting to the area behind an element. Unlike the standard <code>filter</code> property which affects the element itself, <code>backdrop-filter</code> only impacts what's behind it.</p>
<p>For the effect to be visible the element tends to need some kind of semi-transparent background, but this constraint could actually be useful as it can aid and enforce intentional design decisions rather than letting blur become a &quot;visual band-aid&quot;.</p>
<p>It could be particularly useful for creating &quot;glassmorphism&quot; effects - translucent overlays that slightly blur the content beneath (if you really, <em>really</em> felt the need).</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.frosted-glass</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">rgba</span><span class="token punctuation">(</span>255<span class="token punctuation">,</span> 255<span class="token punctuation">,</span> 255<span class="token punctuation">,</span> 0.2<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">blur</span><span class="token punctuation">(</span>10px<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="why-backdrop-filter-is-useful" tabindex="-1">Why backdrop-filter is useful</h2>
<p><code>backdrop-filter</code> opens up design possibilities that would otherwise require heavier workarounds or compromises. Instead of choosing between obscuring content completely or losing visual focus, filters like blur create visual depth and separation with minimal overhead. Overlays and modals can maintain context—the visitor sees the page beneath and intuitively understands they're in a temporary state.</p>
<h2 id="backdrop-filter-options" tabindex="-1">Backdrop-filter options</h2>
<p>The <code>backdrop-filter</code> property accepts the same filter functions as the standard <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/filter"><code>filter</code> property</a>.</p>
<p>Here are the main options:</p>
<h3 id="blur()" tabindex="-1">blur()</h3>
<p>Applies a Gaussian blur to the backdrop. The value defines the blur radius in pixels.</p>
<pre class="language-css"><code class="language-css"><span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">blur</span><span class="token punctuation">(</span>5px<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-g-feature">
<iframe height="300" style="width: 100%;" scrolling="no" title="backdrop-filter: blur" src="https://codepen.io/sturobson/embed/preview/yyaejvK?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/yyaejvK">
  backdrop-filter: blur</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<h3 id="brightness()" tabindex="-1">brightness()</h3>
<p>Adjusts brightness. Values below 100% darken, above 100% brighten. Useful for softening bright backgrounds behind text.</p>
<pre class="language-css"><code class="language-css"><span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">brightness</span><span class="token punctuation">(</span>150%<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-g-feature">
  <iframe height="300" style="width: 100%;" scrolling="no" title="backdrop-filter: brightness" src="https://codepen.io/sturobson/embed/preview/PwGZeBb?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/PwGZeBb">
  backdrop-filter: brightness</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<h3 id="contrast()" tabindex="-1">contrast()</h3>
<p>Adjusts the contrast. Below 100% reduces it, above 100% increases it.</p>
<pre class="language-css"><code class="language-css"><span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">contrast</span><span class="token punctuation">(</span>200%<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-g-feature">
<iframe height="300" style="width: 100%;" scrolling="no" title="backdrop-filter: contrast" src="https://codepen.io/sturobson/embed/preview/vEXLjzN?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/vEXLjzN">
  backdrop-filter: contrast</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<h3 id="grayscale()" tabindex="-1">grayscale()</h3>
<p>Converts the background to greyscale. 100% removes all colour.</p>
<pre class="language-css"><code class="language-css"><span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">grayscale</span><span class="token punctuation">(</span>50%<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-g-feature">
<iframe height="300" style="width: 100%;" scrolling="no" title="backdrop-filter: grayscale" src="https://codepen.io/sturobson/embed/preview/MYjKGZq?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/MYjKGZq">
  backdrop-filter: grayscale</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<h3 id="hue-rotate()" tabindex="-1">hue-rotate()</h3>
<p>Rotates hues around the colour wheel. Values are set in degrees (<code>deg</code>).</p>
<pre class="language-css"><code class="language-css"><span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">hue-rotate</span><span class="token punctuation">(</span>180deg<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-g-feature">
<iframe height="300" style="width: 100%;" scrolling="no" title="backdrop-filter: hue-rotate" src="https://codepen.io/sturobson/embed/preview/QwKyrYQ?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/QwKyrYQ">
  backdrop-filter: hue-rotate</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<h3 id="invert()" tabindex="-1">invert()</h3>
<p>Inverts colours completely. 100% is full inversion.</p>
<pre class="language-css"><code class="language-css"><span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">invert</span><span class="token punctuation">(</span>75%<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-g-feature">
<iframe height="300" style="width: 100%;" scrolling="no" title="backdrop-filter: invert" src="https://codepen.io/sturobson/embed/preview/YPGwLgw?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/YPGwLgw">
  backdrop-filter: invert</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<h3 id="opacity()" tabindex="-1">opacity()</h3>
<p>Adjusts opacity of the backdrop. Lower = more transparent.</p>
<pre class="language-css"><code class="language-css"><span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">opacity</span><span class="token punctuation">(</span>50%<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-g-feature">
  <iframe height="300" style="width: 100%;" scrolling="no" title="backdrop-filter: opacity" src="https://codepen.io/sturobson/embed/preview/ZYpQoPq?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/ZYpQoPq">
  backdrop-filter: opacity</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>Warning: <code>opacity()</code> has very limited browser support. It currently only seems to work in Firefox Nightly and ignores any other filter options in the rule (it ignores the <code>blue()</code> in the above example)</p>
</div>
<h3 id="saturate()" tabindex="-1">saturate()</h3>
<p>Adjusts colour saturation. Above 100% increases it, below decreases.</p>
<pre class="language-css"><code class="language-css"><span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">saturate</span><span class="token punctuation">(</span>200%<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-g-feature">
<iframe height="300" style="width: 100%;" scrolling="no" title="backdrop-filter: saturate" src="https://codepen.io/sturobson/embed/preview/WbGrJVM?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/WbGrJVM">
  backdrop-filter: saturate</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<h3 id="sepia()" tabindex="-1">sepia()</h3>
<p>Applies a sepia tone. 100% is full sepia.</p>
<pre class="language-css"><code class="language-css"><span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">sepia</span><span class="token punctuation">(</span>90%<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-g-feature">
<iframe height="300" style="width: 100%;" scrolling="no" title="backdrop-filter: sepia" src="https://codepen.io/sturobson/embed/preview/JoRGZPj?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/JoRGZPj">
  backdrop-filter: sepia</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<h2 id="combining-multiple-filters" tabindex="-1">Combining multiple filters</h2>
<p>You can stack multiple effects in a single <code>backdrop-filter</code> rule. Blur paired with brightness feels natural:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.glass-overlay</span> <span class="token punctuation">{</span>
  <span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">blur</span><span class="token punctuation">(</span>10px<span class="token punctuation">)</span> <span class="token function">brightness</span><span class="token punctuation">(</span>120%<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<div class="at-g-feature">
<iframe height="300" style="width: 100%;" scrolling="no" title="backdrop-filter: glass overlay" src="https://codepen.io/sturobson/embed/preview/bNwEKqM?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/bNwEKqM">
  backdrop-filter: glass overlay</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<p>But here's the catch: the order you list them in actually changes the result. Filters are applied sequentially, left to right, and each one operates on the output of the previous filter. When color-based filters interact (brightness, contrast, hue-rotate, saturate), the difference becomes visually obvious.</p>
<h2 id="filter-application-order" tabindex="-1">Filter application order</h2>
<p>Compare these two—same filters, different order:</p>
<p><strong>Brightness first, then contrast:</strong></p>
<pre class="language-css"><code class="language-css"><span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">brightness</span><span class="token punctuation">(</span>50%<span class="token punctuation">)</span> <span class="token function">contrast</span><span class="token punctuation">(</span>150%<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-g-feature">
<iframe height="300" style="width: 100%;" scrolling="no" title="backdrop-filter: order 1" src="https://codepen.io/sturobson/embed/preview/NPRxBvK?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/NPRxBvK">
  backdrop-filter: order 1</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<p><strong>Contrast first, then brightness:</strong></p>
<pre class="language-css"><code class="language-css"><span class="token property">backdrop-filter</span><span class="token punctuation">:</span> <span class="token function">contrast</span><span class="token punctuation">(</span>150%<span class="token punctuation">)</span> <span class="token function">brightness</span><span class="token punctuation">(</span>50%<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-g-feature">
<iframe height="300" style="width: 100%;" scrolling="no" title="backdrop-filter: order 2" src="https://codepen.io/sturobson/embed/preview/GgjoBvP?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/GgjoBvP">
  backdrop-filter: order 2</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<p>The first one darkens the backdrop, <em>then</em> applies extreme contrast to those darker values. The second applies contrast to the original colors first, <em>then</em> darkens the result. Blur and spatial effects are less sensitive to order, but always test your combinations to ensure they match your intent.</p>
<h2 id="browser-support" tabindex="-1">Browser support</h2>
<p><code>Backdrop-filter</code> is well supported across modern browsers. Chrome, Edge, Safari, and Firefox all support it.</p>
<p>The vast majority of filter functions work consistently: <code>blur()</code>, <code>brightness()</code>, <code>contrast()</code>, <code>grayscale()</code>, <code>hue-rotate()</code>, <code>invert()</code>, and <code>saturate()</code> are all broadly compatible. Where things get tricky is the newer or more experimental filters that some browsers haven't fully implemented yet.</p>
<p><code>opacity()</code> and <code>drop-shadow()</code> are the two filters that seem to, currently, have some significant limitations. As of this writing, <code>opacity()</code> only has reliable support in Firefox Nightly; it's ignored in Chrome, Edge, and Safari. Similarly, <code>drop-shadow()</code> currently only works in Firefox Nightly and looks to be unsupported elsewhere. If you need these effects, they're safe to use as progressively enhanced features, but don't rely on them as core functionality.</p>
<p>For robust support for colour and blur-based effects, stick with the filters that have universal adoption: <code>blur()</code> paired with <code>brightness()</code>, <code>contrast()</code>, or <code>grayscale()</code> gives you everything you need for glassmorphism effects without compatibility worry.</p>
<h2 id="wrapping-up" tabindex="-1">Wrapping up</h2>
<p><code>Backdrop-filter</code> is a pretty straightforward property. Pair it with a semi-transparent background, pick your filter(s) (blur is most useful), and test on real devices. The main trick is remembering that transparency is generally required for the effect to show.</p>
<h3 id="try-it-yourself" tabindex="-1">Try it yourself</h3>
<p>Play with all backdrop-filter options live in this CodePen—adjust blur, brightness, contrast, saturation, and more to see how they combine:</p>
<div class="at-g-feature">
<iframe height="600" style="width: 100%;" scrolling="no" title="Beyond The Blur - a backdrop-filter demo" src="https://codepen.io/sturobson/embed/raMxdQz/04ad816b434c583c27f2322243e64f24?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/raMxdQz/04ad816b434c583c27f2322243e64f24">
  Beyond The Blur - a backdrop-filter demo</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 15) - Managing Microcopy with Design Tokens and Style Dictionary</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-15.html"/>
      <updated>2026-03-03T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-15.html</id>
      <content type="html">
        <![CDATA[
        <p>When we talk about design tokens, we usually mean colours, spacing, typography, and other visual properties. But there's another layer of design that's critical and rarely managed systematically: microcopy.</p>
<p>Microcopy is the small pieces of text scattered throughout your interface: button labels, form hints, error messages, empty states, confirmation dialogs. While we version control colour palettes and spacing scales, interface copy is commonly hardcoded into components, scattered across files, and inconsistently managed across platforms.</p>
<p>I was first introduced to microcopy in web design by <a href="https://www.linkedin.com/in/relly-annett-baker/">Relly</a>, and later during a workshop <a href="https://www.jina.me">Jina</a> ran in 2019, they mentioned how tokens could be a perfect fit for managing microcopy systematically.</p>
<p>These aren't mere strings. An error message that says &quot;Error&quot; versus &quot;Please enter a valid email address&quot; is a deliberate design decision affecting comprehension, trust, and conversion. A button labelled &quot;OK&quot; versus &quot;Save changes&quot; guides user behavior. If you want to follow along with a working example whilst reading this article, the <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/15-microcopy-tokens">Style Dictionary Starter includes a complete microcopy setup</a> you can explore and experiment with.</p>
<p>The problem is there could be no single source of truth. You can't say &quot;all our primary action buttons should say 'Continue'&quot; without hunting through dozens of files. When you need to update an error message, you would be hunting through codebases rather than updating a token. Designers, copywriters, and product managers can't propose changes without potentially diving into code or visiting every screen to be sure.</p>
<p>But, what if we could manage microcopy the same way we manage colours, spacing, and typography?</p>
<h2 id="why-manage-microcopy-as-tokens%3F" tabindex="-1">Why Manage Microcopy as Tokens?</h2>
<p>Managing microcopy in this way can give us several benefits.</p>
<p>First, you get consistency across your entire product. The language doesn't shift from &quot;Save&quot; in one place to &quot;Submit&quot; in another. Accessibility becomes part of the design by default: labels, aria-labels, and descriptions all defined in one place.</p>
<p>For teams supporting multiple languages, localisation becomes straightforward. Instead of managing separate systems with different schemas, you maintain a single token structure with language specific layers. Edit the JSON, rebuild, deploy.</p>
<p>Your product's brand voice comes through consistently across the entire interface, while team collaboration improves because everyone can participate. Every change can flow through git. You can roll back instantly, see who changed what and why, and maintain a complete trail.</p>
<p>Finally, you generate platform specific output from one source. JavaScript objects for web, Swift dictionaries for iOS, XML for Android. One source of truth for every platform.</p>
<h2 id="understanding-the-w3c-specification" tabindex="-1">Understanding the W3C Specification</h2>
<p>Here's where it gets a little interesting.</p>
<p>The W3C Design Tokens Community Group specification doesn't currently include a <code>content</code> or <code>string</code> type. The spec defines:</p>
<h3 id="basic-types" tabindex="-1">Basic types</h3>
<ul>
<li><code>color</code></li>
<li><code>dimension</code></li>
<li><code>fontFamily</code></li>
<li><code>fontWeight</code></li>
<li><code>duration</code></li>
<li><code>cubicBezier</code></li>
<li><code>number</code></li>
</ul>
<h3 id="composite-types" tabindex="-1">Composite types</h3>
<ul>
<li><code>strokeStyle</code></li>
<li><code>border</code></li>
<li><code>transition</code></li>
<li><code>shadow</code></li>
<li><code>gradient</code></li>
<li><code>typography</code></li>
</ul>
<p>No <code>content</code>. No <code>string</code>.</p>
<p>Since every token must have a valid <code>$type</code>, we have a specification gap.</p>
<p>How can we add microcopy? We will have to work around this.</p>
<p>We can either inherit a <code>$type</code> from a parent group or acknowledge we're extending the spec beyond what it currently supports. The best practice is to set <code>$type</code> at the group level, your microcopy group can declare a type, and then use <code>$extensions</code> to mark which tokens are actually microcopy.</p>
<p>Remember the article on <a href="https://www.alwaystwisted.com/articles/understanding-extensions-in-the-design-tokens-spec">Understanding $extensions in the Design Tokens Specification</a>?</p>
<p>This is exactly what it's designed for. Adding custom, tool-specific data without breaking the standard. Microcopy is a perfect use case.</p>
<h2 id="structuring-microcopy-tokens" tabindex="-1">Structuring Microcopy Tokens</h2>
<p>A well organised microcopy token structure mirrors how developers think about interfaces. Group content by context (forms, navigation, feedback) and component type (button, input, modal), using the same hierarchical approach you'd apply to colours or spacing.</p>
<p>I recommend something like this structure:</p>
<pre><code>tokens/
  copy.tokens.json         # Root file with group-level $type
  copy-button.tokens.json  # Button labels
  copy-form.tokens.json    # Form labels, hints, placeholders
  copy-error.tokens.json   # Validation, system, and UI state messages
</code></pre>
<p>This keeps all token files in the same <code>tokens/</code> folder for simplicity. The root file establishes the group structure, while category files contain the actual token definitions.</p>
<h2 id="creating-microcopy-tokens-with-%24extensions" tabindex="-1">Creating Microcopy Tokens With <code>$extensions</code></h2>
<p>The spec requires every token to have a valid <code>$type</code>. Since there's no <code>string</code> type, we set <code>$type</code> at the group level (using a placeholder type like <code>number</code>) and rely on <code>$extensions</code> to identify microcopy tokens. This is a pragmatic workaround to an acknowledged gap in the spec.</p>
<p>Start by creating the root token file <code>tokens/copy.tokens.json</code>:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"copy"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"number"</span><span class="token punctuation">,</span>
    <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Microcopy tokens. Type is set here to satisfy spec requirements; use $extensions to identify actual microcopy tokens."</span><span class="token punctuation">,</span>
    <span class="token property">"button"</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"form"</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"error"</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>This root file serves as the group-level container for all microcopy tokens. By setting <code>$type</code> at the top level, all child tokens inherit this type, eliminating the need to repeat <code>$type</code> in every individual <code>tokens.json</code> file. The empty objects (<code>&quot;button&quot;: {}</code>, etc.) define the structure without containing actual token values.</p>
<p>Now create button labels in <code>tokens/copy-button.tokens.json</code>:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"copy"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"button"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"label"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Continue"</span><span class="token punctuation">,</span>
          <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Primary action button label"</span><span class="token punctuation">,</span>
          <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
              <span class="token property">"category"</span><span class="token operator">:</span> <span class="token string">"button"</span><span class="token punctuation">,</span>
              <span class="token property">"context"</span><span class="token operator">:</span> <span class="token string">"primary-action"</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"label"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Cancel"</span><span class="token punctuation">,</span>
          <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
              <span class="token property">"category"</span><span class="token operator">:</span> <span class="token string">"button"</span><span class="token punctuation">,</span>
              <span class="token property">"context"</span><span class="token operator">:</span> <span class="token string">"secondary-action"</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"submit"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"label"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Submit"</span><span class="token punctuation">,</span>
          <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
              <span class="token property">"category"</span><span class="token operator">:</span> <span class="token string">"button"</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"delete"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"label"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Delete"</span><span class="token punctuation">,</span>
          <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
              <span class="token property">"category"</span><span class="token operator">:</span> <span class="token string">"button"</span><span class="token punctuation">,</span>
              <span class="token property">"context"</span><span class="token operator">:</span> <span class="token string">"destructive"</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"confirm"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Are you sure you want to delete this item?"</span><span class="token punctuation">,</span>
          <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
              <span class="token property">"category"</span><span class="token operator">:</span> <span class="token string">"button"</span><span class="token punctuation">,</span>
              <span class="token property">"context"</span><span class="token operator">:</span> <span class="token string">"destructive-confirm"</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Now form related copy in <code>tokens/copy-form.tokens.json</code>:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"copy"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"form"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"input"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"email"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"label"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Email address"</span><span class="token punctuation">,</span>
            <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token property">"placeholder"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"you@example.com"</span><span class="token punctuation">,</span>
            <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token property">"hint"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"We'll never share your email with anyone else"</span><span class="token punctuation">,</span>
            <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"password"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"label"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Password"</span><span class="token punctuation">,</span>
            <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token property">"placeholder"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Enter your password"</span><span class="token punctuation">,</span>
            <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token property">"hint"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Must be at least 8 characters"</span><span class="token punctuation">,</span>
            <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Error and UI state messages in <code>tokens/copy-error.tokens.json</code>:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"copy"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"error"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"validation"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"required"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"This field is required"</span><span class="token punctuation">,</span>
          <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"email"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"invalid"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Please enter a valid email address"</span><span class="token punctuation">,</span>
            <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"password"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"tooShort"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Password must be at least 8 characters"</span><span class="token punctuation">,</span>
            <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token property">"mismatch"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Passwords do not match"</span><span class="token punctuation">,</span>
            <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="generating-microcopy-with-style-dictionary" tabindex="-1">Generating Microcopy With Style Dictionary</h2>
<p>Now that we have our tokens structured with <code>$extensions</code>, we need to get them into our build pipeline. We'll create custom Style Dictionary formats that output JavaScript and JSON from the same source.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>Since the DTCG spec doesn't define a string type, we used <code>$type: number</code> as a placeholder at the group level in our token definitions. This allows tokens to be valid according to the spec while we use <code>$extensions</code> to identify actual microcopy. The key is that Style Dictionary can filter based on the extension, which is what matters for our build.</p>
</div>
<p>Create a <code>build.js</code> file to build your microcopy tokens:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token comment">// Filter tokens to get only microcopy tokens based on extensions</span>
<span class="token keyword">const</span> <span class="token function-variable function">getMicrocopyTokens</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">dictionary</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      token<span class="token punctuation">.</span>$extensions <span class="token operator">&amp;&amp;</span>
      token<span class="token punctuation">.</span>$extensions<span class="token punctuation">[</span><span class="token string">'com.alwaystwisted.microcopy'</span><span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span>
      token<span class="token punctuation">.</span>$extensions<span class="token punctuation">[</span><span class="token string">'com.alwaystwisted.microcopy'</span><span class="token punctuation">]</span><span class="token punctuation">.</span>enabled
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token comment">// Build a nested object from flat token paths</span>
<span class="token keyword">const</span> <span class="token function-variable function">buildNestedObject</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">tokens</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>

  tokens<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> path <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Skip 'copy' prefix from path</span>
    <span class="token keyword">let</span> current <span class="token operator">=</span> result<span class="token punctuation">;</span>

    path<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">key<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>index <span class="token operator">===</span> path<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// Set the value at the final key</span>
        current<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> token<span class="token punctuation">.</span>$value<span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        <span class="token comment">// Create nested object if it doesn't exist</span>
        current<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> current<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">||</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
        current <span class="token operator">=</span> current<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom format for JavaScript ES6 export</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'javascript/microcopy'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> nested <span class="token operator">=</span> <span class="token function">buildNestedObject</span><span class="token punctuation">(</span><span class="token function">getMicrocopyTokens</span><span class="token punctuation">(</span>dictionary<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">export const microcopy = </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>nested<span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom format for JSON output</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'json/microcopy'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> nested <span class="token operator">=</span> <span class="token function">buildNestedObject</span><span class="token punctuation">(</span><span class="token function">getMicrocopyTokens</span><span class="token punctuation">(</span>dictionary<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>nested<span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> config <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'tokens/**/*.tokens.json'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// Source files for tokens</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">js</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'js'</span><span class="token punctuation">,</span> <span class="token comment">// Use JavaScript transforms</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/js/'</span><span class="token punctuation">,</span> <span class="token comment">// Output directory</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'microcopy.js'</span><span class="token punctuation">,</span> <span class="token comment">// Output file</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'javascript/microcopy'</span><span class="token punctuation">,</span> <span class="token comment">// Use custom format</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">json</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'js'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/json/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'microcopy.json'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'json/microcopy'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> sd <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">await</span> sd<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Run the build with <code>node build.js</code> and you'll get:</p>
<pre><code>build/
  js/
    microcopy.js
  json/
    microcopy.json
</code></pre>
<p>For example, <code>build/js/microcopy.js</code> gives you a nested object:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">export</span> <span class="token keyword">const</span> microcopy <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">button</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">primary</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">label</span><span class="token operator">:</span> <span class="token string">'Continue'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">secondary</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">label</span><span class="token operator">:</span> <span class="token string">'Cancel'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">submit</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">label</span><span class="token operator">:</span> <span class="token string">'Submit'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token keyword">delete</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">label</span><span class="token operator">:</span> <span class="token string">'Delete'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">confirm</span><span class="token operator">:</span> <span class="token string">'Are you sure you want to delete this item?'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token comment">// ... ,,,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h2 id="using-microcopy-tokens-in-components" tabindex="-1">Using Microcopy Tokens in Components</h2>
<p>Now you can use this in your components with clean, semantic references.</p>
<h3 id="react-example" tabindex="-1">React Example</h3>
<p>Here's a simple sign-up form demonstrating microcopy token usage:</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> <span class="token punctuation">{</span> microcopy <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./build/js/microcopy.js'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> useState <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">SignUpForm</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// State for form input</span>
  <span class="token keyword">const</span> <span class="token punctuation">[</span>email<span class="token punctuation">,</span> setEmail<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token punctuation">(</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span><span class="token punctuation">></span></span><span class="token plain-text">
      </span><span class="token punctuation">{</span><span class="token comment">/* Email input using microcopy tokens for label and placeholder */</span><span class="token punctuation">}</span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form-group<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text">
        </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">htmlFor</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token punctuation">{</span>microcopy<span class="token punctuation">.</span>form<span class="token punctuation">.</span>input<span class="token punctuation">.</span>email<span class="token punctuation">.</span>label<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span><span class="token plain-text">
        </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span>
          <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span>
          <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span>
          <span class="token attr-name">placeholder</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>microcopy<span class="token punctuation">.</span>form<span class="token punctuation">.</span>input<span class="token punctuation">.</span>email<span class="token punctuation">.</span>placeholder<span class="token punctuation">}</span></span>
          <span class="token attr-name">value</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>email<span class="token punctuation">}</span></span>
          <span class="token attr-name">onChange</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">setEmail</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">}</span></span>
        <span class="token punctuation">/></span></span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><span class="token plain-text">

      </span><span class="token punctuation">{</span><span class="token comment">/* Submit button using microcopy token for text */</span><span class="token punctuation">}</span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>submit<span class="token punctuation">"</span></span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn-primary<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text">
        </span><span class="token punctuation">{</span>microcopy<span class="token punctuation">.</span>button<span class="token punctuation">.</span>submit<span class="token punctuation">.</span>label<span class="token punctuation">}</span><span class="token plain-text">
      </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span><span class="token plain-text">
    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>form</span><span class="token punctuation">></span></span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This is far more readable than hardcoded strings. Instead of <code>&lt;button&gt;Submit&lt;/button&gt;</code>, you have a semantic reference that clearly identifies which piece of text you're using. When a copywriter updates the token, every instance updates automatically.</p>
<h3 id="vanilla-javascript-validation" tabindex="-1">Vanilla JavaScript Validation</h3>
<p>Here's a simple validation function using microcopy:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> microcopy <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./build/js/microcopy.js'</span><span class="token punctuation">;</span>

<span class="token comment">// Validate email with microcopy messages</span>
<span class="token keyword">function</span> <span class="token function">validateEmail</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>value <span class="token operator">||</span> value<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token string">''</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token literal-property property">valid</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token literal-property property">message</span><span class="token operator">:</span> microcopy<span class="token punctuation">.</span>error<span class="token punctuation">.</span>validation<span class="token punctuation">.</span>required <span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">const</span> emailRegex <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^[^\s@]+@[^\s@]+\.[^\s@]+$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>emailRegex<span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token literal-property property">valid</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token literal-property property">message</span><span class="token operator">:</span> microcopy<span class="token punctuation">.</span>error<span class="token punctuation">.</span>validation<span class="token punctuation">.</span>email<span class="token punctuation">.</span>invalid <span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token literal-property property">valid</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// Usage</span>
<span class="token keyword">const</span> emailInput <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#email'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> errorElement <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'.error-message'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

emailInput<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'blur'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token function">validateEmail</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
  errorElement<span class="token punctuation">.</span>textContent <span class="token operator">=</span> result<span class="token punctuation">.</span>valid <span class="token operator">?</span> <span class="token string">''</span> <span class="token operator">:</span> result<span class="token punctuation">.</span>message<span class="token punctuation">;</span>
  errorElement<span class="token punctuation">.</span>style<span class="token punctuation">.</span>display <span class="token operator">=</span> result<span class="token punctuation">.</span>valid <span class="token operator">?</span> <span class="token string">'none'</span> <span class="token operator">:</span> <span class="token string">'block'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The validator is completely decoupled from actual messages. Update the tokens, rebuild, and validation messages update everywhere automatically.</p>
<h2 id="multi-language-support-through-token-layers" tabindex="-1">Multi-Language Support Through Token Layers</h2>
<p>Design tokens really shine for internationalization. Instead of managing separate i18n files with different structures, use the same token architecture you use for theming.</p>
<p>Create language-specific token files. Set <code>$type</code> at the group level (using our placeholder approach), then override the values:</p>
<p><strong><code>tokens/copy-en-button.tokens.json</code></strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"copy"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"button"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"label"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Continue"</span><span class="token punctuation">,</span>
          <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"label"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Cancel"</span><span class="token punctuation">,</span>
          <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong><code>tokens/copy-fr-button.tokens.json</code></strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"copy"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"button"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"label"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Continuer"</span><span class="token punctuation">,</span>
          <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"label"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Annuler"</span><span class="token punctuation">,</span>
          <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"com.alwaystwisted.microcopy"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"enabled"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Create a <code>build-i18n.js</code> file for multi-language builds:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom format for JavaScript ES6 export (multi-language version)</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'javascript/microcopy'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// Filter to get only microcopy tokens</span>
    <span class="token keyword">const</span> microcopyTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token punctuation">(</span>
        token<span class="token punctuation">.</span>$extensions <span class="token operator">&amp;&amp;</span>
        token<span class="token punctuation">.</span>$extensions<span class="token punctuation">[</span><span class="token string">'com.alwaystwisted.microcopy'</span><span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span>
        token<span class="token punctuation">.</span>$extensions<span class="token punctuation">[</span><span class="token string">'com.alwaystwisted.microcopy'</span><span class="token punctuation">]</span><span class="token punctuation">.</span>enabled
      <span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// Build nested object from token paths</span>
    <span class="token keyword">const</span> <span class="token function-variable function">buildNestedObject</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">tokens</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
      tokens<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> path <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Skip 'copy' prefix</span>
        <span class="token keyword">let</span> current <span class="token operator">=</span> result<span class="token punctuation">;</span>
        path<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">key<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
          <span class="token keyword">if</span> <span class="token punctuation">(</span>index <span class="token operator">===</span> path<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            current<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> token<span class="token punctuation">.</span>$value<span class="token punctuation">;</span>
          <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
            current<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> current<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">||</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
            current <span class="token operator">=</span> current<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">;</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> result<span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>

    <span class="token keyword">const</span> nested <span class="token operator">=</span> <span class="token function">buildNestedObject</span><span class="token punctuation">(</span>microcopyTokens<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">export const microcopy = </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>nested<span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// List of supported languages</span>
<span class="token keyword">const</span> languages <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'en'</span><span class="token punctuation">,</span> <span class="token string">'fr'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

<span class="token comment">// Build microcopy for each language</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">const</span> language <span class="token keyword">of</span> languages<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> config <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">tokens/copy-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>language<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">-*.tokens.json</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// Language-specific token files</span>
    <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">js</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'js'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">build/js/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>language<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token comment">// Output to language-specific directory</span>
        <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
          <span class="token punctuation">{</span>
            <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'microcopy.js'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'javascript/microcopy'</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> sd <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">await</span> sd<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Run the multi-language build with <code>node build-i18n.js</code>.</p>
<p>This creates:</p>
<pre><code>build/
  js/
    en/microcopy.js
    fr/microcopy.js
</code></pre>
<p>With identical structure, just different copy.</p>
<h2 id="why-this-approach-works" tabindex="-1">Why This Approach Works</h2>
<p>Using <code>$extensions</code> for microcopy keeps your tokens valid according to the DTCG spec. Other tools can parse your files without breaking, even if they don't understand your extensions. When the spec evolves, the DTCG is actively discussing it, so you can migrate seamlessly.</p>
<p>More importantly, it treats microcopy as a first-class citizen in your design system. It's not an afterthought. It's not a hack. It's part of your core token infrastructure, managed the same way you manage colours, spacing, and typography. For a complete working implementation, refer to the <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/15-microcopy-tokens">Style Dictionary Starter repository</a>.</p>
<p>Your interface copy directly impacts how users understand, trust, and succeed with your product. It deserves systematic management, version control, collaboration, and the same attention you give to visual design.</p>
<p>Start small. Tokenise your error messages. Then expand. You'll wonder how you ever managed microcopy any other way.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Building Fluid Typographic Scales with clamp() and :heading()</title>
      <link href="https://www.alwaystwisted.com/articles/building-fluid-typographic-scales-with-clamp-and-heading.html"/>
      <updated>2026-02-19T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/building-fluid-typographic-scales-with-clamp-and-heading.html</id>
      <content type="html">
        <![CDATA[
        <p>In the last article, I showed how to use explicit <code>:heading(N)</code> level mapping with <code>pow()</code> to create mathematical typographic scales. This article extends that approach to fluid scaling with <code>clamp()</code>, so your heading sizes adapt smoothly to the viewport instead of jumping at breakpoints.</p>
<h2 id="the-fluid-typography-formula" tabindex="-1">The Fluid Typography Formula</h2>
<p>Fluid typography scales smoothly with the viewport instead of jumping at breakpoints. With <code>clamp()</code>, you define a minimum size, a maximum size, and the viewport boundaries—the maths calculates the scaling automatically, keeping text within those bounds.</p>
<p>The underlying formula is a linear ramp between your minimum and maximum viewport widths:</p>
<pre class="language-css"><code class="language-css"><span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token function">clamp</span><span class="token punctuation">(</span>
  min-size<span class="token punctuation">,</span>
  min-size + <span class="token punctuation">(</span>max-size - min-size<span class="token punctuation">)</span> *
    <span class="token punctuation">(</span><span class="token punctuation">(</span>100vw - min-viewport<span class="token punctuation">)</span> / <span class="token punctuation">(</span>max-viewport - min-viewport<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  max-size
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Where:</p>
<ul>
<li><strong>min-size</strong>: Smallest font size (e.g., 1rem)</li>
<li><strong>max-size</strong>: Largest font size (e.g., 2rem)</li>
<li><strong>min-viewport</strong>: Viewport width where scaling starts (e.g., 375px)</li>
<li><strong>max-viewport</strong>: Viewport width where scaling stops (e.g., 1440px)</li>
</ul>
<p>You can calculate these values by hand, or use tools like <a href="https://utopia.fyi">Utopia</a>, <a href="https://www.fluidtypography.com">Fluid Typography</a>, or <a href="https://typefluidity.com">Type Fluidity</a> to experiment with different ratios and sizes before implementing.</p>
<h2 id="implementing-with-%3Aheading()" tabindex="-1">Implementing with :heading()</h2>
<p>The <code>:heading()</code> pseudo-class lets you write the sizing logic once in a single <code>:heading</code> rule, then map each heading level to a number. Compare that to writing separate font-size calculations for h1, h2, h3, h4, h5, h6.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p><strong>Why explicit level mapping:</strong> <code>:heading(N) { --heading-level: X; }</code> stays reliable regardless of your HTML structure—h1 stays h1 even with repeated or skipped heading levels.</p>
</div>
<p>By writing the sizing logic in one <code>:heading</code> block, all the maths lives in a single place. To change how the scale works, you edit one place instead of duplicating calculations across h1, h2, h3, h4, h5, h6.</p>
<p>The level mapping is simple, <code>:heading(1) { --heading-level: 5; }</code> is a one-liner. You set a number rather than writing the entire clamp() calculation for each heading.</p>
<p>Because you're explicitly mapping <code>:heading(N)</code> to <code>--heading-level</code> values, your headings size correctly regardless of HTML structure. h3 stays h3 even if your markup has repeated heading levels.</p>
<p>Finally, it's design system friendly. Change the <code>:root</code> variables once, and every heading updates instantly across your entire project.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p><strong>Why h1 = level 5, not 1 or 6?</strong> The maths works with exponents. An exponent of 0 gives you the base size: h6 = 1rem × 1.2^0 = 1rem. Counting up from 0 means h1's larger exponent (5) naturally produces a larger size: 1rem × 1.2^5 ≈ 2.49rem. If we started h1 at 1, the scale would be inverted. If we started at 6, h6 would be 1rem × 1.2^6, not the base size.</p>
</div>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token comment">/* Viewport boundaries for fluid scaling */</span>
  <span class="token property">--fluid-min</span><span class="token punctuation">:</span> 375px<span class="token punctuation">;</span> <span class="token comment">/* where scaling starts */</span>
  <span class="token property">--fluid-max</span><span class="token punctuation">:</span> 1440px<span class="token punctuation">;</span> <span class="token comment">/* where scaling stops */</span>
  <span class="token property">--fluid-range</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--fluid-max<span class="token punctuation">)</span> - <span class="token function">var</span><span class="token punctuation">(</span>--fluid-min<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">/* Base font size: min at 375px viewport, max at 1440px */</span>
  <span class="token property">--base-min</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--base-max</span><span class="token punctuation">:</span> 1.125rem<span class="token punctuation">;</span>

  <span class="token comment">/* Musical scale ratios (pick one by changing --scale-min and --scale-max) */</span>
  <span class="token property">--scale-minor-second</span><span class="token punctuation">:</span> 1.067<span class="token punctuation">;</span>
  <span class="token property">--scale-major-second</span><span class="token punctuation">:</span> 1.125<span class="token punctuation">;</span>
  <span class="token property">--scale-minor-third</span><span class="token punctuation">:</span> 1.2<span class="token punctuation">;</span>
  <span class="token property">--scale-major-third</span><span class="token punctuation">:</span> 1.25<span class="token punctuation">;</span>
  <span class="token property">--scale-perfect-fourth</span><span class="token punctuation">:</span> 1.333<span class="token punctuation">;</span>
  <span class="token property">--scale-augmented-fourth</span><span class="token punctuation">:</span> 1.414<span class="token punctuation">;</span>
  <span class="token property">--scale-perfect-fifth</span><span class="token punctuation">:</span> 1.5<span class="token punctuation">;</span>
  <span class="token property">--scale-golden-ratio</span><span class="token punctuation">:</span> 1.618<span class="token punctuation">;</span>

  <span class="token comment">/* Set your scales here */</span>
  <span class="token property">--scale-min</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--scale-minor-third<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--scale-max</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--scale-perfect-fourth<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">:heading</span> <span class="token punctuation">{</span>
  <span class="token property">--exponent</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-level<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">/* Calculate min and max sizes for this heading level */</span>
  <span class="token property">--size-min</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--base-min<span class="token punctuation">)</span> * <span class="token function">pow</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--scale-min<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--exponent<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--size-max</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--base-max<span class="token punctuation">)</span> * <span class="token function">pow</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--scale-max<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--exponent<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">/* Linear ramp: (max - min) / viewport-range scaled to 100vw */</span>
  <span class="token property">--fluid-rate</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>
    <span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--size-max<span class="token punctuation">)</span> - <span class="token function">var</span><span class="token punctuation">(</span>--size-min<span class="token punctuation">)</span><span class="token punctuation">)</span> * 100 / <span class="token function">var</span><span class="token punctuation">(</span>--fluid-range<span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token function">clamp</span><span class="token punctuation">(</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--size-min<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--size-min<span class="token punctuation">)</span> + <span class="token function">var</span><span class="token punctuation">(</span>--fluid-rate<span class="token punctuation">)</span> * <span class="token punctuation">(</span>100vw - <span class="token function">var</span><span class="token punctuation">(</span>--fluid-min<span class="token punctuation">)</span><span class="token punctuation">)</span> / 100<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--size-max<span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">:heading(1)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-level</span><span class="token punctuation">:</span> 5<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">:heading(2)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-level</span><span class="token punctuation">:</span> 4<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">:heading(3)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-level</span><span class="token punctuation">:</span> 3<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">:heading(4)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-level</span><span class="token punctuation">:</span> 2<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">:heading(5)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-level</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">:heading(6)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-level</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Each heading level gets its own fluid rate because the size-range grows exponentially with the exponent. h1 scales more aggressively than h6, maintaining the typographic ratio across all viewport sizes.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p><strong>Accessibility Note:</strong> This approach complies with WCAG 1.4.4 (Resize Text) because the <code>clamp()</code> min/max values use <code>rem</code> units, which scale with browser zoom. Viewport units only control the rate of change between viewport widths—they don't prevent zooming. Always use <code>rem</code> (never <code>px</code>) and test with browser zoom at different viewport widths.</p>
</div>
<h2 id="browser-support" tabindex="-1">Browser Support</h2>
<p><code>clamp()</code> has excellent support across all modern browsers (Chrome 79+, Firefox 75+, Safari 13.1+). The <code>:heading()</code> pseudo-class and <code>pow()</code> function are currently experimental and only available in Safari Technology Preview.</p>
<p>If you want to track progress or add support signals for the missing pieces:</p>
<ul>
<li><a href="https://issues.chromium.org/issues/438147580"><code>:heading</code> (Chrome)</a></li>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1953973"><code>:heading</code> (Firefox)</a></li>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1782527"><code>pow()</code> (Firefox)</a></li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Building Typographic Scales in CSS with :heading(), sibling-index(), and pow()</title>
      <link href="https://www.alwaystwisted.com/articles/building-typographic-scales-with-headings-sibling-index-and-pow.html"/>
      <updated>2026-02-17T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/building-typographic-scales-with-headings-sibling-index-and-pow.html</id>
      <content type="html">
        <![CDATA[
        <p>In <a href="https://www.alwaystwisted.com/articles/styling-with-the-heading-pseudo-class">my previous article</a>, I introduced the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:heading"><code>:heading</code> pseudo-class</a> and showed how it can simplify styling all headings in groups, or all at once. Today, I want to take that much further and show how combining <code>:heading()</code> with two other CSS features—<code>sibling-index()</code> and <code>pow()</code> lets us build flexible, maintainable typographic scales with just a few lines of code.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p><strong>Important limitation:</strong> <code>sibling-index()</code> counts <em>siblings</em>, not heading levels. That means the scale only lines up if you have a clean, ordered run of <code>h1</code> → <code>h6</code>. If you repeat a heading level (for example: <code>h1</code>, <code>h2</code>, <code>h3</code>, <code>h3</code>), the second <code>h3</code> will be sized like <code>h4</code> because its sibling index is higher. Keep that in mind if you use this pattern in real layouts.</p>
</div>
<p>There’s still a lot to like here, but the ordering limitation matters in real content.</p>
<p>If you want the version that works regardless of heading order, skip to <a href="#what-works-in-real-layouts">What Works in Real Layouts</a>.</p>
<h2 id="the-problem-with-traditional-typographic-scales" tabindex="-1">The Problem with Traditional Typographic Scales</h2>
<p>When you implement a typographic scale in CSS today, you may end up with something like this.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">h1</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 3.052rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">h2</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 2.441rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">h3</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 1.953rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">h4</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 1.563rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">h5</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 1.25rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">h6</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This works, but it's repetitive.</p>
<p>Separate declarations for what's essentially a mathematical pattern. It may be inflexible too. Want to try a different ratio? You'll need to recalculate all the values manually, which could be error prone when dealing with exponential calculations. The relationship between values isn't expressed in the code itself, which could make it harder to understand and maintain.</p>
<p>What we really want is to define the pattern once and let CSS calculate the individual values for us.</p>
<h2 id="understanding-typographic-scales" tabindex="-1">Understanding Typographic Scales</h2>
<p>Typographic scales use ratios (mostly) borrowed from musical intervals. These ratios create &quot;harmonious&quot; proportions because they're based on the same mathematical relationships that make good music feel right.</p>
<p>Common scales:</p>
<ul>
<li>Minor Third (1.200) - Subtle</li>
<li>Major Third (1.250) - Balanced</li>
<li>Perfect Fourth (1.333) - Slightly more dramatic</li>
<li>Perfect Fifth (1.500) - Bold</li>
<li>Golden Ratio (1.618) - Not a musical interval, but commonly used</li>
</ul>
<p>These scales are exponential, not linear. Each heading level multiplies the previous level by the ratio, rather than adding to it.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p><strong>Exponential vs Linear:</strong> With a linear scale, each step adds the same fixed amount. With an exponential scale, each step multiplies by the ratio—so you get bigger jumps between larger sizes. That's why h1 is so much bigger than h2, which is bigger than h3, and so on, and so on, and so on.</p>
</div>
<p>Here's what that exponential growth looks like across heading levels with a Major Third scale (1.25):</p>
<pre><code>h6: 1rem × 1.25⁰ = 1rem
h5: 1rem × 1.25¹ = 1.25rem
h4: 1rem × 1.25² = 1.563rem
h3: 1rem × 1.25³ = 1.953rem
h2: 1rem × 1.25⁴ = 2.441rem
h1: 1rem × 1.25⁵ = 3.052rem
</code></pre>
<p>The pattern, base-size × ratio ^ exponent.</p>
<p>This is where <code>pow()</code> comes in.</p>
<h2 id="enter-pow()%3A-exponentiation-in-css" tabindex="-1">Enter pow(): Exponentiation in CSS</h2>
<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/pow"><code>pow()</code> function</a> is part of <a href="https://www.w3.org/TR/css-values-4/">CSS Values and Units Level 4</a>. It calculates a number raised to a power (<a href="https://en.wikipedia.org/wiki/Exponentiation">exponentiation</a>) in CSS.</p>
<pre class="language-css"><code class="language-css"><span class="token function">pow</span><span class="token punctuation">(</span>base<span class="token punctuation">,</span> exponent<span class="token punctuation">)</span></code></pre>
<p>For example:</p>
<ul>
<li><code>pow(2, 3) = 2³ = 8</code></li>
<li><code>pow(1.25, 4) = 1.25⁴ = 2.441</code></li>
</ul>
<p>This is exactly what we need to help calculate typographic scales. Instead of manually computing 1.25 × 1.25 × 1.25 × 1.25, we can write <code>pow(1.25, 4)</code>.</p>
<h2 id="the-missing-piece%3A-sibling-index()" tabindex="-1">The Missing Piece: sibling-index()</h2>
<p>Here's how it works in the ideal case. The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/sibling-index"><code>sibling-index()</code> function</a> returns the position of an element among its siblings, starting from 1 (it works with any elements, not just <code>:heading</code>).</p>
<p>In a typical demo where <code>h1</code> through <code>h6</code> are siblings in order, that index lines up with the heading level:</p>
<ul>
<li>h1 has <code>sibling-index() = 1</code></li>
<li>h2 has <code>sibling-index() = 2</code></li>
<li>h3 has <code>sibling-index() = 3</code></li>
<li>And so on...</li>
</ul>
<p>This means we can use <code>sibling-index()</code> to calculate the size dynamically for each heading level.</p>
<h2 id="putting-it-all-together" tabindex="-1">Putting It All Together</h2>
<p>Here's the full pattern in action:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--font-size-base</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--scale-major-third</span><span class="token punctuation">:</span> 1.25<span class="token punctuation">;</span>
  <span class="token property">--typographic-scale</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--scale-major-third<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">:heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--font-size-base<span class="token punctuation">)</span> * <span class="token function">pow</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--typographic-scale<span class="token punctuation">)</span><span class="token punctuation">,</span> 6 - <span class="token function">sibling-index</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>That's it. Three custom properties and one font-size rule.</p>
<p>Let's break down what's happening. First, <code>6 - sibling-index()</code> calculates the exponent for each heading. For h1 (index 1) it becomes <code>6 - 1 = 5</code>, for h2 it becomes <code>6 - 2 = 4</code>, and for h6 it becomes <code>6 - 6 = 0</code>.</p>
<p>Next, <code>pow(var(--typographic-scale), ...)</code> raises the scale ratio to that exponent. With a 1.25 ratio, h1 becomes <code>pow(1.25, 5) = 3.052</code>, h2 becomes <code>pow(1.25, 4) = 2.441</code>, and h6 becomes <code>pow(1.25, 0) = 1</code>.</p>
<p>Finally, <code>var(--font-size-base) * ...</code> multiplies that result by the base size so the whole scale can move up or down together.</p>
<p>The result is that h1 is the largest, h6 is the base size, and everything in between follows the exponential scale perfectly.</p>
<p>If you want a one-line mental model, it's this: <strong>font-size = base-size x ratio^(6 - sibling-index())</strong>. With a Perfect Fourth scale (1.333), that gives you a range from h1 at 4.209rem down to h6 at 1rem, with each heading level stepping down by the same ratio.</p>
<h2 id="building-a-complete-scale-system" tabindex="-1">Building a Complete Scale System</h2>
<p>Let's expand this into a practical system with multiple scale options:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token comment">/* Scale ratios based on musical intervals */</span>
  <span class="token property">--scale-minor-second</span><span class="token punctuation">:</span> 1.067<span class="token punctuation">;</span>
  <span class="token property">--scale-major-second</span><span class="token punctuation">:</span> 1.125<span class="token punctuation">;</span>
  <span class="token property">--scale-minor-third</span><span class="token punctuation">:</span> 1.2<span class="token punctuation">;</span>
  <span class="token property">--scale-major-third</span><span class="token punctuation">:</span> 1.25<span class="token punctuation">;</span>
  <span class="token property">--scale-perfect-fourth</span><span class="token punctuation">:</span> 1.333<span class="token punctuation">;</span>
  <span class="token property">--scale-augmented-fourth</span><span class="token punctuation">:</span> 1.414<span class="token punctuation">;</span>
  <span class="token property">--scale-perfect-fifth</span><span class="token punctuation">:</span> 1.5<span class="token punctuation">;</span>
  <span class="token property">--scale-golden-ratio</span><span class="token punctuation">:</span> 1.618<span class="token punctuation">;</span>

  <span class="token comment">/* Active scale - change this to switch globally */</span>
  <span class="token property">--typographic-scale</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--scale-major-third<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">/* Base size and max level for clarity */</span>
  <span class="token property">--heading-base-size</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--heading-max-level</span><span class="token punctuation">:</span> 6<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">:heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--heading-base-size<span class="token punctuation">)</span> *
      <span class="token function">pow</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--typographic-scale<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-max-level<span class="token punctuation">)</span> - <span class="token function">sibling-index</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Now you can experiment with different scales by changing a single variable. Want to try a Perfect Fourth scale? Just update <code>--typographic-scale</code>:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--typographic-scale</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--scale-perfect-fourth<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Every heading on your site instantly updates to the new scale.</p>
<p>You can also nudge the overall size up or down by adjusting <code>--heading-base-size</code>.</p>
<h2 id="responsive-typography" tabindex="-1">Responsive Typography</h2>
<p>Several years ago I attended an amazing workshop from <a href="https://clagnut.com">Rich</a> on responsive web typography, and one thing stuck with me. You don't have to use the same scale across all devices. Narrow viewports can use a tighter scale, while larger viewports can breathe a little more. Using the system we've created, we can adjust the scale based on viewport size.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--typographic-scale</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--scale-minor-third<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Smaller scale on mobile to prevent oversized headings */</span>
<span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span>width >= 768px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
  <span class="token selector">:root</span> <span class="token punctuation">{</span>
    <span class="token property">--typographic-scale</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--scale-major-third<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Larger scale on big screens where you have more space */</span>
<span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span>width >= 1400px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
  <span class="token selector">:root</span> <span class="token punctuation">{</span>
    <span class="token property">--typographic-scale</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--scale-perfect-fourth<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="practical-example%3A-a-complete-design-system" tabindex="-1">Practical Example: A Complete Design System</h2>
<p>Here's how you might structure this in a real design system:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token comment">/* Color tokens */</span>
  <span class="token property">--color-heading</span><span class="token punctuation">:</span> #2c3e50<span class="token punctuation">;</span>
  <span class="token property">--color-heading-secondary</span><span class="token punctuation">:</span> #546e7a<span class="token punctuation">;</span>

  <span class="token comment">/* Typography scales */</span>
  <span class="token property">--scale-minor-third</span><span class="token punctuation">:</span> 1.2<span class="token punctuation">;</span>
  <span class="token property">--scale-major-third</span><span class="token punctuation">:</span> 1.25<span class="token punctuation">;</span>
  <span class="token property">--scale-perfect-fourth</span><span class="token punctuation">:</span> 1.333<span class="token punctuation">;</span>
  <span class="token property">--scale-augmented-fourth</span><span class="token punctuation">:</span> 1.414<span class="token punctuation">;</span>
  <span class="token property">--scale-perfect-fifth</span><span class="token punctuation">:</span> 1.5<span class="token punctuation">;</span>
  <span class="token property">--scale-golden-ratio</span><span class="token punctuation">:</span> 1.618<span class="token punctuation">;</span>

  <span class="token comment">/* Active scale */</span>
  <span class="token property">--typographic-scale</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--scale-minor-third<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">/* Base values */</span>
  <span class="token property">--heading-base-size</span><span class="token punctuation">:</span> 0.9375rem<span class="token punctuation">;</span>
  <span class="token property">--heading-max-level</span><span class="token punctuation">:</span> 6<span class="token punctuation">;</span>
  <span class="token property">--heading-font-weight</span><span class="token punctuation">:</span> 600<span class="token punctuation">;</span>
  <span class="token property">--heading-font-weight--strong</span><span class="token punctuation">:</span> 700<span class="token punctuation">;</span>
  <span class="token property">--heading-line-height</span><span class="token punctuation">:</span> 1.2<span class="token punctuation">;</span>
  <span class="token property">--heading-letter-spacing</span><span class="token punctuation">:</span> -0.02em<span class="token punctuation">;</span>
  <span class="token property">--heading-letter-spacing--tight</span><span class="token punctuation">:</span> -0.03em<span class="token punctuation">;</span>
  <span class="token property">--heading-letter-spacing--loose</span><span class="token punctuation">:</span> -0.01em<span class="token punctuation">;</span>
  <span class="token property">--heading-letter-spacing--caps</span><span class="token punctuation">:</span> 0.05em<span class="token punctuation">;</span>

  <span class="token comment">/* Spacing */</span>
  <span class="token property">--spacing-heading-block</span><span class="token punctuation">:</span> 1.5rem 0.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Base heading styles */</span>
<span class="token selector">:heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--heading-base-size<span class="token punctuation">)</span> *
      <span class="token function">pow</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--typographic-scale<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-max-level<span class="token punctuation">)</span> - <span class="token function">sibling-index</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-family-heading<span class="token punctuation">,</span> <span class="token string">'Georgia'</span><span class="token punctuation">,</span> serif<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">font-weight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-font-weight<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">line-height</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-line-height<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">letter-spacing</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-letter-spacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-heading<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">margin-block</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-heading-block<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">word-wrap</span><span class="token punctuation">:</span> break-word<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Tiered weights */</span>
<span class="token selector">:heading(1, 2, 3)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-font-weight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-font-weight--strong<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--heading-letter-spacing</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-letter-spacing--tight<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">:heading(4, 5, 6)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-font-weight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-font-weight<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--heading-letter-spacing</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-letter-spacing--loose<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-heading-secondary<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Special case for h6 */</span>
<span class="token selector">:heading(6)</span> <span class="token punctuation">{</span>
  <span class="token property">text-transform</span><span class="token punctuation">:</span> uppercase<span class="token punctuation">;</span>
  <span class="token property">--heading-letter-spacing</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-letter-spacing--caps<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Responsive adjustments */</span>
<span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span>width >= 768px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
  <span class="token selector">:root</span> <span class="token punctuation">{</span>
    <span class="token property">--typographic-scale</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--scale-major-third<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">--heading-base-size</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span>width >= 1400px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
  <span class="token selector">:root</span> <span class="token punctuation">{</span>
    <span class="token property">--typographic-scale</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--scale-perfect-fourth<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Dark mode */</span>
<span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
  <span class="token selector">:root</span> <span class="token punctuation">{</span>
    <span class="token property">--color-heading</span><span class="token punctuation">:</span> #ecf0f1<span class="token punctuation">;</span>
    <span class="token property">--color-heading-secondary</span><span class="token punctuation">:</span> #bdc3c7<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>This follows Mike's <a href="https://www.smashingmagazine.com/2018/05/css-custom-properties-strategy-guide/">cascading custom property strategy</a>, so css custom properties can be overridden contextually without duplicating rules.</p>
</div>
<p>This gives you a complete, flexible, maintainable heading system. It keeps mathematical precision for sizing, adapts to different contexts, responds to viewport size, supports theming, and can be updated globally with a single variable change.</p>
<h2 id="what-works-in-real-layouts" tabindex="-1">What Works in Real Layouts</h2>
<p>If you want the scale to work even when headings repeat or skip levels, you can assign the level explicitly and keep the maths intact. This removes the dependency on sibling order.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-base-size</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--typographic-scale</span><span class="token punctuation">:</span> 1.25<span class="token punctuation">;</span> <span class="token comment">/* Major Third */</span>
<span class="token punctuation">}</span>

<span class="token selector">:heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--heading-base-size<span class="token punctuation">)</span> *
      <span class="token function">pow</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--typographic-scale<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-level<span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">:heading(1)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-level</span><span class="token punctuation">:</span> 5<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">:heading(2)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-level</span><span class="token punctuation">:</span> 4<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">:heading(3)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-level</span><span class="token punctuation">:</span> 3<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">:heading(4)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-level</span><span class="token punctuation">:</span> 2<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">:heading(5)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-level</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">:heading(6)</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-level</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>It’s a few more lines, but it behaves correctly no matter how your headings are ordered in the markup.</p>
<div class="at-g-feature">
    <iframe height="600" style="width: 100%;" scrolling="no" title="Typographic Scales with :heading(), pow, and sibling-index()" src="https://codepen.io/sturobson/embed/KwMLKLg?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
      See the Pen <a href="https://codepen.io/sturobson/pen/KwMLKLg">
  Typographic Scales with :heading(), pow, and sibling-index()</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
      </iframe>
</div>
<h2 id="why-this-matters" tabindex="-1">Why This Matters</h2>
<p>This approach nudges how we think about CSS. Instead of declaring individual values, we're defining systems and letting CSS calculate the details.</p>
<p>Values update based on context, viewport, and user preferences. The mathematical relationship is expressed once and applied everywhere. Want to try a different scale? Change one variable. Want to adjust all heading sizes? Change the base size. The relationships remain consistent.</p>
<h2 id="browser-support-and-testing" tabindex="-1">Browser Support and Testing</h2>
<p>Safari Technology Preview is currently the only browser that supports all three features used here.</p>
<p>If you want to track progress or add support signals, here are the two issues to star or follow:</p>
<ul>
<li><a href="https://issues.chromium.org/issues/438147580"><code>:heading</code> (Chrome)</a></li>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1953973"><code>sibling-index()</code> (Firefox)</a></li>
<li><a href="https://bugs.webkit.org/show_bug.cgi?id=296994"><code>:heading</code> and <code>heading()</code> (Safari)</a></li>
</ul>
<h2 id="wrapping-up" tabindex="-1">Wrapping Up</h2>
<p>The combination of <code>:heading()</code>, <code>sibling-index()</code>, and <code>pow()</code> can transform typographic scales from a tedious process into an elegant, mathematical system.</p>
<p>You define the rules once, and CSS handles the calculations.</p>
<p>This is more than a convenience feature.</p>
<p>It's a glimpse into a future where we can express design systems as mathematical relationships rather than exhaustive declarations. The code becomes more maintainable and more flexible.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Style Headings using the CSS :heading pseudo-class</title>
      <link href="https://www.alwaystwisted.com/articles/styling-with-the-heading-pseudo-class.html"/>
      <updated>2026-02-16T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/styling-with-the-heading-pseudo-class.html</id>
      <content type="html">
        <![CDATA[
        <p>The <code>:heading</code> pseudo-class lets us target all heading elements (<code>h1</code> through <code>h6</code>) with a single CSS rule, rather than writing out a verbose selector group every time we need to.</p>
<p>It's a small change, but it represents a shift toward better, more intentional and 'semantic' CSS.</p>
<h2 id="the-current-approach" tabindex="-1">The Current Approach</h2>
<p>Before <code>:heading</code>, whenever we wanted to apply the same styles to some or all headings, we had to list every heading element:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">h1,
h2,
h3,
h4,
h5,
h6</span> <span class="token punctuation">{</span>
  <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token string">'Georgia'</span><span class="token punctuation">,</span> serif<span class="token punctuation">;</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #333<span class="token punctuation">;</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
  <span class="token property">margin-bottom</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This works perfectly fine, but it's kinda verbose, especially if we're resetting some rules for specific headings. And if we're working with a large codebase or two, we might find ourselves repeating this pattern across multiple files.</p>
<p>It's not exactly a disaster, but it feels a bit untidy.</p>
<h2 id="enter-%3Aheading" tabindex="-1">Enter <code>:heading</code></h2>
<p>The <code>:heading</code> pseudo-class solves this with a cleaner, more semantic syntax:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token string">'Georgia'</span><span class="token punctuation">,</span> serif<span class="token punctuation">;</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #333<span class="token punctuation">;</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
  <span class="token property">margin-bottom</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This is much nicer, it clearly reads &quot;for all heading elements, apply these styles.&quot;. The intent should be immediately obvious. Here's what that looks like in action:</p>
<div class="at-g-feature">
<iframe height="600" style="width: 100%;" scrolling="no" title=":heading example" src="https://codepen.io/sturobson/embed/MYexYJq??default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
      See the Pen <a href="https://codepen.io/sturobson/pen/MYexYJq/826492d5570a5ac12bb402b8c4a55a37">
  :heading example</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
      </iframe>
</div>
<h2 id="targeting-specific-heading-levels" tabindex="-1">Targeting Specific Heading Levels</h2>
<p>While <code>:heading</code> lets us target all headings at once, we often want to apply different styles to different heading levels. The <code>:heading()</code> functional notation lets us do this by grouping heading levels together:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Major headings - larger and bolder */</span>
<span class="token selector">:heading(1, 2, 3)</span> <span class="token punctuation">{</span>
  <span class="token property">font-weight</span><span class="token punctuation">:</span> 700<span class="token punctuation">;</span>
  <span class="token property">letter-spacing</span><span class="token punctuation">:</span> -0.02em<span class="token punctuation">;</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Secondary headings - smaller and lighter */</span>
<span class="token selector">:heading(4, 5, 6)</span> <span class="token punctuation">{</span>
  <span class="token property">font-weight</span><span class="token punctuation">:</span> 600<span class="token punctuation">;</span>
  <span class="token property">letter-spacing</span><span class="token punctuation">:</span> -0.01em<span class="token punctuation">;</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 1.25rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This approach of grouping headings into &quot;tiers&quot; within the design system lets us apply different styling rules without listing out each individual heading element (h1, h2, h3, etc.).</p>
<p>As a working principle, use <code>:heading</code> for properties that should be universal (font-family, line-height), and <code>:heading()</code> when different levels genuinely need different treatments (font-size, font-weight).</p>
<h3 id="specificity-considerations" tabindex="-1">Specificity Considerations</h3>
<p>One little thing to keep in mind: <code>:heading</code> has a specificity that's the same as a class selector (<code>0-1-0</code>).</p>
<p>Compare this to the old multi-selector approach:</p>
<ul>
<li><code>:heading</code> = <code>0-1-0</code></li>
<li><code>h1, h2, h3, h4, h5, h6</code> = <code>0-0-1</code></li>
</ul>
<p>This means that <code>:heading</code> should override styles on individual heading elements if both are present. This is usually what we want, but it's worth noting this for when we're debugging cascade issues.</p>
<h2 id="some-possible-use-cases" tabindex="-1">Some Possible Use Cases</h2>
<h3 id="consistent-typography" tabindex="-1">Consistent Typography</h3>
<p>The most straightforward use case is ensuring all headings follow the same typographic rules:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-weight</span><span class="token punctuation">:</span> 600<span class="token punctuation">;</span>
  <span class="token property">line-height</span><span class="token punctuation">:</span> 1.2<span class="token punctuation">;</span>
  <span class="token property">letter-spacing</span><span class="token punctuation">:</span> -0.02em<span class="token punctuation">;</span>
  <span class="token property">word-wrap</span><span class="token punctuation">:</span> break-word<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This keeps our heading hierarchy consistent without having to repeat ourselves. Line height, letter spacing, and font weight are the kinds of properties that should be uniform across all heading levels, and <code>:heading</code> lets us set them once.</p>
<h3 id="component-specific-heading-styles" tabindex="-1">Component-Specific Heading Styles</h3>
<p>In component systems, the same heading level (say, an h3) might need different treatments depending on where it lives. With <code>:heading</code>, we set base styles once, then customise per-component:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Base heading styles that apply everywhere */</span>
<span class="token selector">:heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-family-heading<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">font-weight</span><span class="token punctuation">:</span> 600<span class="token punctuation">;</span>
  <span class="token property">line-height</span><span class="token punctuation">:</span> 1.2<span class="token punctuation">;</span>
  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-heading<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* In a card, headings get a bottom border and different color */</span>
<span class="token selector">.card :heading</span> <span class="token punctuation">{</span>
  <span class="token property">border-bottom</span><span class="token punctuation">:</span> 2px solid <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-card-heading<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding-bottom</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* In a sidebar, headings are smaller and uppercase */</span>
<span class="token selector">.sidebar :heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 0.875rem<span class="token punctuation">;</span>
  <span class="token property">text-transform</span><span class="token punctuation">:</span> uppercase<span class="token punctuation">;</span>
  <span class="token property">letter-spacing</span><span class="token punctuation">:</span> 0.05em<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* In modals, headings get extra spacing */</span>
<span class="token selector">.modal :heading</span> <span class="token punctuation">{</span>
  <span class="token property">margin-bottom</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Without <code>:heading</code>, we'd define the base font, weight, and line-height separately for each component selector. With <code>:heading</code>, we define them once and let components add only the differences they need.</p>
<h3 id="font-family-and-weight-enforcement-across-components" tabindex="-1">Font Family and Weight Enforcement Across Components</h3>
<p>In a component system, a title in a Card, a heading in a Modal, and a subtitle in a Hero section could all share the same foundational typography—same font family, same font weight, same line height, but they just differ in font size.</p>
<p>With <code>:heading</code>, this is easy:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* All headings across the entire system */</span>
<span class="token selector">:heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token string">'Inter'</span><span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
  <span class="token property">font-weight</span><span class="token punctuation">:</span> 600<span class="token punctuation">;</span>
  <span class="token property">line-height</span><span class="token punctuation">:</span> 1.2<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Each component only customises what's unique to it */</span>
<span class="token selector">.card :heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 1.25rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.modal :heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.hero :heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 2.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Without <code>:heading</code>, we'd have to repeat the font-family, font-weight, and line-height in every component:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Without :heading - repetitive and fragile */</span>
<span class="token selector">.card h1,
.card h2,
.card h3,
.card h4,
.card h5,
.card h6</span> <span class="token punctuation">{</span>
  <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token string">'Inter'</span><span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
  <span class="token property">font-weight</span><span class="token punctuation">:</span> 600<span class="token punctuation">;</span>
  <span class="token property">line-height</span><span class="token punctuation">:</span> 1.2<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card h1</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 1.25rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.card h2</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 1.1rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* ... and repeat for modal, hero, etc. */</span>

<span class="token selector">.modal h1,
.modal h2,
.modal h3,
.modal h4,
.modal h5,
.modal h6</span> <span class="token punctuation">{</span>
  <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token string">'Inter'</span><span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
  <span class="token property">font-weight</span><span class="token punctuation">:</span> 600<span class="token punctuation">;</span>
  <span class="token property">line-height</span><span class="token punctuation">:</span> 1.2<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.modal h1</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* ... and again for hero ... */</span></code></pre>
<h2 id="composing-%3Aheading-with-other-selectors" tabindex="-1">Composing :heading With Other Selectors</h2>
<p>Beyond component-specific styles, <code>:heading</code> works well with other CSS patterns:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Variant modifiers - useful for design system components */</span>
<span class="token selector">:heading.error</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-error<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">:heading.success</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-success<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Sibling combinator - manage spacing between consecutive headings */</span>
<span class="token selector">:heading + :heading</span> <span class="token punctuation">{</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Headings inside interactive elements */</span>
<span class="token selector">button :heading,
a :heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> inherit<span class="token punctuation">;</span>
  <span class="token property">margin</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>These patterns avoid repeating the same rule for h1, h2, h3, etc. in each context. This composability is what makes <code>:heading</code> so valuable in larger systems.</p>
<h2 id="browser-support-and-testing" tabindex="-1">Browser Support and Testing</h2>
<p>The <code>:heading</code> pseudo-class is currently available in nightly builds only. You can test it now in:</p>
<ul>
<li>Firefox Nightly (behind a flag)</li>
<li>Safari Technology Preview</li>
</ul>
<p>If you want to see this in Chrome you can <a href="https://issues.chromium.org/issues/438147580">star this issue</a></p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>The more developers who test <code>:heading</code> in nightly builds and advocate for the feature, the faster it's likely to be prioritised for stable release. Browser vendors pay attention to developer adoption and demand.</p>
</div>
<h2 id="a-cleaner-design-system" tabindex="-1">A Cleaner Design System</h2>
<p>If we're building a design system or component library, <code>:heading</code> can be particularly useful.</p>
<p>We can define base heading styles once and know they'll apply everywhere:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Base heading styles with defaults */</span>
<span class="token selector">:heading</span> <span class="token punctuation">{</span>
  <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-family-heading<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">font-weight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-font-weight<span class="token punctuation">,</span> 600<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">line-height</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-line-height<span class="token punctuation">,</span> 1.2<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-heading<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">margin-block</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-heading-block<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--heading-font-size<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Heading-specific variations using custom property overrides */</span>
<span class="token selector">h1</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-font-size</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-h1<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">h2</span> <span class="token punctuation">{</span>
  <span class="token property">--heading-font-size</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-h2<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* And so on... */</span></code></pre>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>This approach follows <a href="https://www.smashingmagazine.com/2018/05/css-custom-properties-strategy-guide/">Mike Riethmuller's strategy</a> of using CSS custom properties to create overrideable defaults. Set custom properties that cascade naturally and get picked up by the base <code>:heading</code> rule, and we'll reduce repetition while making it easier to customise individual heading levels.</p>
</div>
<h2 id="wrapping-up" tabindex="-1">Wrapping Up</h2>
<p>The <code>:heading</code> pseudo-class is a small but lovely addition to CSS that will make styling headings feel less repetitive.</p>
<p>Combined with CSS custom properties, it can become even more powerful, letting us manage heading styles consistently across entire design systems with minimal code.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 14) - Using Notion With Style Dictionary for Design Tokens Management</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-14.html"/>
      <updated>2026-02-09T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-14.html</id>
      <content type="html">
        <![CDATA[
        <p>Design tokens are great for developers, but what about everyone else on your team? The designers, product managers, and stakeholders who need to contribute without touching code?</p>
<p>JSON files work well for machines, but they're not exactly inviting for non-technical folks. That's where Notion comes in. It's the perfect bridge between your design system and the rest of your organisation.</p>
<p>In this tutorial, I'll show you how to set up a collaborative design token workflow using Notion as a user-friendly interface and Style Dictionary to generate platform-specific output. Changes made in Notion automatically sync to your codebase, and you can even push edits back for team review.</p>
<p>All the code and scripts mentioned in this tutorial are available in a <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/14-notion-design-tokens">GitHub repository for easy download and use</a></p>
<h2 id="benefits-of-this-approach" tabindex="-1">Benefits of This Approach</h2>
<p>Using Notion for design token management offers several advantages:</p>
<ul>
<li><strong>Accessibility</strong>: Non-technical team members can view, comment on, and propose token changes without touching code</li>
<li><strong>Collaboration</strong>: Built-in comments, version history, and real-time updates keep the team synchronised</li>
<li><strong>Organization</strong>: Database views allow filtering, sorting, and organizing tokens by category, status, or type</li>
<li><strong>Documentation</strong>: Rich content can be added alongside token values for context and usage guidelines</li>
<li><strong>Approval Workflow</strong>: Status fields manage which tokens are draft, in review, approved, or deprecated</li>
</ul>
<h2 id="setting-up-your-notion-database" tabindex="-1">Setting Up Your Notion Database</h2>
<p>Create a Notion database with the following properties:</p>
<ul>
<li><strong>Name</strong> (Title): The token name (e.g., &quot;Primary Blue&quot;)</li>
<li><strong>Token Path</strong> (Text): The path Style Dictionary will use (e.g., &quot;color.brand.primary&quot;)</li>
<li><strong>Value</strong> (Text): The actual value (e.g., &quot;#007bff&quot;)</li>
<li><strong>Type</strong> (Select): The token type (color, dimension, fontFamily, fontWeight, etc.)</li>
<li><strong>Category</strong> (Select): How the token is grouped (brand, semantic, component, foundation, etc.)</li>
<li><strong>Description</strong> (Text): Notes on what the token is for and when to use it</li>
<li><strong>Status</strong> (Select): Draft, Review, Approved, Deprecated</li>
</ul>
<figure class="at-c-figure--article-image at-g-popout">
  <img 
    src="/images/articles/notion/notion-database-categorgies.jpg" 
    alt="Screenshot of an empty Notion database showing column headers for design token properties"
    loading="lazy"
  >
  <figcaption>A Notion database configured with properties for Name, Token Path, Value, Type, Category, Description, and Status columns.</figcaption>
</figure>
<p>Once your database is set up with these properties, you can start adding your design tokens. The <strong>Status</strong> field controls which tokens get synced. By default, only &quot;Approved&quot; tokens are pulled into your build, creating a natural approval workflow before changes reach production.</p>
<figure class="at-c-figure--article-image at-g-popout">
  <img 
    src="/images/articles/notion/notion-database.jpg" 
    alt="Notion database with example tokens"
    loading="lazy"
  >
  <figcaption>A populated Notion database showing three example design tokens: Primary Blue (color), Base Spacing (dimension), and Heading Font (fontFamily). Each token has its corresponding properties filled in and Status set to Approved.</figcaption>
</figure>
<h3 id="token-path-format" tabindex="-1">Token Path Format</h3>
<p>The <strong>Token Path</strong> determines the structure of your generated CSS variables.</p>
<ul>
<li>Use dot notation: <code>color.brand.primary</code> becomes <code>--color-brand-primary</code></li>
<li>Each level creates a nested structure: <code>typography.size.base</code> becomes <code>--typography-size-base</code></li>
<li>Nested paths organise your token tree in the JSON output</li>
</ul>
<p>The Style Dictionary build will succeed even with incorrect paths, but won't generate what you expect.</p>
<h2 id="setting-up-the-notion-integration" tabindex="-1">Setting Up the Notion Integration</h2>
<p>Connecting Notion to your build process requires several steps. Complete them in order.</p>
<h3 id="step-1%3A-create-the-integration" tabindex="-1">Step 1: Create the Integration</h3>
<ol>
<li>Go to <a href="https://www.notion.com/my-integrations">https://www.notion.com/my-integrations</a></li>
<li>Click <strong>+ New integration</strong></li>
<li>Give it a name (e.g., &quot;Design Tokens Sync&quot;)</li>
<li>Select your workspace</li>
<li>Under <strong>Capabilities</strong>, make sure &quot;Read content&quot; is checked</li>
<li>Click <strong>Save</strong></li>
<li>Copy your <strong>Internal Integration Token</strong> (the long string starting with <code>ntn_</code>)</li>
<li>Store this securely, it's your API key for accessing Notion</li>
</ol>
<figure class="at-c-figure--article-image at-g-popout">
  <img 
    src="/images/articles/notion/notion-my-integration-page.jpg" 
    alt="Notion My Integrations page"
    loading="lazy"
  >
  <figcaption>The Notion My integrations page showing the integration creation form with fields for Name (Design Tokens Sync), Workspace selection, and Capabilities toggle with Read content enabled.</figcaption>
</figure>
<p>After creating the integration, you'll see the integration details page where you can copy your <strong>Internal Integration Token</strong>.</p>
<figure class="at-c-figure--article-image at-g-popout">
  <img 
    src="/images/articles/notion/notion-integration-settings.jpg" 
    alt="Notion integration token"
    loading="lazy"
  >
  <figcaption>The successfully created integration showing the Internal Integration Token field with the token value (redacted in production) ready to be copied. Note the security warning to keep this token secure.</figcaption>
</figure>
<h3 id="step-2%3A-get-your-database-id" tabindex="-1">Step 2: Get Your Database ID</h3>
<p>You need the actual <em>database</em> ID, not the parent page ID.</p>
<ol>
<li>Open your Notion database (the table view)</li>
<li>Copy the URL from your browser</li>
<li>It looks like: <code>https://www.notion.so/abc123def456ghi789jkl?v=xyz&amp;t=123</code></li>
<li>The database ID is the part <strong>before the <code>?v=</code></strong> (the long hex string)</li>
<li>Save this ID</li>
</ol>
<h3 id="step-3%3A-connect-the-integration-to-your-database" tabindex="-1">Step 3: Connect the Integration to Your Database</h3>
<p>This step is critical, skipping it causes &quot;database not found&quot; errors.</p>
<ol>
<li>Open your Notion database</li>
<li>Click the <strong>•••</strong> menu in the top right corner</li>
<li>Scroll to <strong>Connections</strong></li>
<li>Click <strong>+ Add connections</strong> (or <strong>Confirm access</strong> if shown)</li>
<li>Select your integration name</li>
<li>Confirm access</li>
</ol>
<figure class="at-c-figure--article-image at-g-popout">
  <img 
    src="/images/articles/notion/notion-database-menu.jpg" 
    alt="Notion database menu"
    loading="lazy"
  >
  <figcaption>The Notion database page with the three-dot menu in the top right corner expanded, showing various options including the Connections section.</figcaption>
</figure>
<p>From the menu, select <strong>+ Add connections</strong> to grant your integration access to this specific database.</p>
<figure class="at-c-figure--article-image at-g-popout">
  <img 
    src="/images/articles/notion/notion-add-connections.jpg" 
    alt="Notion add connections dialog"
    loading="lazy"
  >
  <figcaption>The Add connections dialog showing the list of available integrations. The Design Tokens Sync integration is highlighted and ready to be selected to grant database access.</figcaption>
</figure>
<p>The integration now has permission to read from that database. Without this, the API will reject all requests with a 404 error.</p>
<h3 id="step-4%3A-set-up-your-development-environment" tabindex="-1">Step 4: Set Up Your Development Environment</h3>
<p>Now that your Notion integration is configured, let's set up your local development environment.</p>
<p>First, install the required npm packages:</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> @notionhq/client style-dictionary dotenv nodemon</code></pre>
<p>Create a <code>.env</code> file in your project root with your Notion credentials:</p>
<pre class="language-env"><code class="language-env">NOTION_TOKEN=ntn_your_long_token_here
NOTION_DATABASE_ID=abc123def456ghi789jkl</code></pre>
<p>Make sure your <code>package.json</code> has <code>&quot;type&quot;: &quot;module&quot;</code> so you can use ES modules:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"module"</span><span class="token punctuation">,</span>
  <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"design-tokens"</span><span class="token punctuation">,</span>
  <span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"1.0.0"</span><span class="token punctuation">,</span>
  ...
<span class="token punctuation">}</span></code></pre>
<p>That's it! You're ready to sync.</p>
<h2 id="fetching-tokens-from-notion" tabindex="-1">Fetching Tokens from Notion</h2>
<p>Create a file called <code>fetch-tokens.js</code> that pulls approved tokens from Notion and generates a JSON file for Style Dictionary.</p>
<p>First, let's set up the imports and initialise the Notion client:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> Client <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@notionhq/client'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> fs <span class="token keyword">from</span> <span class="token string">'fs'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> path <span class="token keyword">from</span> <span class="token string">'path'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> fileURLToPath <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'url'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> dotenv <span class="token keyword">from</span> <span class="token string">'dotenv'</span><span class="token punctuation">;</span>

dotenv<span class="token punctuation">.</span><span class="token function">config</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> __filename <span class="token operator">=</span> <span class="token function">fileURLToPath</span><span class="token punctuation">(</span><span class="token keyword">import</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> __dirname <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">dirname</span><span class="token punctuation">(</span>__filename<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Initialise Notion client</span>
<span class="token keyword">const</span> notion <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Client</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">auth</span><span class="token operator">:</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NOTION_TOKEN</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> databaseId <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NOTION_DATABASE_ID</span><span class="token punctuation">;</span></code></pre>
<p>Next, create a function to fetch all approved tokens from your Notion database. This handles pagination since Notion returns results in batches:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">/**
 * Fetch all approved tokens from Notion database
 */</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fetchTokensFromNotion</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> allResults <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token keyword">let</span> hasMore <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
    <span class="token keyword">let</span> startCursor <span class="token operator">=</span> <span class="token keyword">undefined</span><span class="token punctuation">;</span>

    <span class="token comment">// Handle pagination</span>
    <span class="token keyword">while</span> <span class="token punctuation">(</span>hasMore<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token keyword">await</span> notion<span class="token punctuation">.</span>databases<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">database_id</span><span class="token operator">:</span> databaseId<span class="token punctuation">,</span>
        <span class="token literal-property property">start_cursor</span><span class="token operator">:</span> startCursor<span class="token punctuation">,</span>
        <span class="token literal-property property">filter</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'Status'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">select</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">equals</span><span class="token operator">:</span> <span class="token string">'Approved'</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

      allResults <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">...</span>allResults<span class="token punctuation">,</span> <span class="token operator">...</span>response<span class="token punctuation">.</span>results<span class="token punctuation">]</span><span class="token punctuation">;</span>
      hasMore <span class="token operator">=</span> response<span class="token punctuation">.</span>has_more<span class="token punctuation">;</span>
      startCursor <span class="token operator">=</span> response<span class="token punctuation">.</span>next_cursor<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">return</span> allResults<span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">'Error fetching from Notion:'</span><span class="token punctuation">,</span> error<span class="token punctuation">.</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">throw</span> error<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Now we need a function to extract the token data from Notion's page properties format into a simpler structure:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">/**
 * Extract token data from Notion page properties
 */</span>
<span class="token keyword">function</span> <span class="token function">extractTokenData</span><span class="token punctuation">(</span><span class="token parameter">page</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> properties <span class="token operator">=</span> page<span class="token punctuation">.</span>properties<span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">id</span><span class="token operator">:</span> page<span class="token punctuation">.</span>id<span class="token punctuation">,</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span> properties<span class="token punctuation">.</span>Name<span class="token operator">?.</span>title<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">?.</span>plain_text <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
    <span class="token literal-property property">path</span><span class="token operator">:</span> properties<span class="token punctuation">[</span><span class="token string">'Token Path'</span><span class="token punctuation">]</span><span class="token operator">?.</span>rich_text<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">?.</span>plain_text <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
    <span class="token literal-property property">value</span><span class="token operator">:</span> properties<span class="token punctuation">.</span>Value<span class="token operator">?.</span>rich_text<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">?.</span>plain_text <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
    <span class="token literal-property property">type</span><span class="token operator">:</span> properties<span class="token punctuation">.</span>Type<span class="token operator">?.</span>select<span class="token operator">?.</span>name <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
    <span class="token literal-property property">category</span><span class="token operator">:</span> properties<span class="token punctuation">.</span>Category<span class="token operator">?.</span>select<span class="token operator">?.</span>name <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
    <span class="token literal-property property">status</span><span class="token operator">:</span> properties<span class="token punctuation">.</span>Status<span class="token operator">?.</span>select<span class="token operator">?.</span>name <span class="token operator">||</span> <span class="token string">'Draft'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">description</span><span class="token operator">:</span> properties<span class="token punctuation">.</span>Description<span class="token operator">?.</span>rich_text<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">?.</span>plain_text <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>The tokens need to be converted from a flat list into a nested JSON structure that Style Dictionary can understand. This function builds that tree:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">/**
 * Convert flat token list to nested JSON structure
 */</span>
<span class="token keyword">function</span> <span class="token function">buildTokenTree</span><span class="token punctuation">(</span><span class="token parameter">tokens</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> tree <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>

  tokens<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> pathParts <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">'.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">let</span> current <span class="token operator">=</span> tree<span class="token punctuation">;</span>

    pathParts<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">part<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>index <span class="token operator">===</span> pathParts<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// Last part - add the token</span>
        current<span class="token punctuation">[</span>part<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">$value</span><span class="token operator">:</span> token<span class="token punctuation">.</span>value<span class="token punctuation">,</span>
          <span class="token literal-property property">$type</span><span class="token operator">:</span> token<span class="token punctuation">.</span>type<span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span>token<span class="token punctuation">.</span>description<span class="token punctuation">)</span> <span class="token punctuation">{</span>
          current<span class="token punctuation">[</span>part<span class="token punctuation">]</span><span class="token punctuation">.</span>$description <span class="token operator">=</span> token<span class="token punctuation">.</span>description<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// Add Notion metadata as extensions</span>
        current<span class="token punctuation">[</span>part<span class="token punctuation">]</span><span class="token punctuation">.</span>$extensions <span class="token operator">=</span> <span class="token punctuation">{</span>
          <span class="token string-property property">'com.notion'</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">status</span><span class="token operator">:</span> token<span class="token punctuation">.</span>status<span class="token punctuation">,</span>
            <span class="token literal-property property">category</span><span class="token operator">:</span> token<span class="token punctuation">.</span>category<span class="token punctuation">,</span>
            <span class="token literal-property property">notionId</span><span class="token operator">:</span> token<span class="token punctuation">.</span>id<span class="token punctuation">,</span>
            <span class="token literal-property property">lastSynced</span><span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toISOString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        <span class="token comment">// Create nested object if it doesn't exist</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>current<span class="token punctuation">[</span>part<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          current<span class="token punctuation">[</span>part<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        current <span class="token operator">=</span> current<span class="token punctuation">[</span>part<span class="token punctuation">]</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> tree<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>To detect conflicts between local changes and Notion updates, we need to flatten the nested token structure back into an array for comparison:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">/**
 * Flatten nested token object back into array (for comparison/conflict detection)
 */</span>
<span class="token keyword">function</span> <span class="token function">flattenTokens</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> prefix <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> tokens <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

  Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">key</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> fullPath <span class="token operator">=</span> prefix <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>prefix<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>key<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> key<span class="token punctuation">;</span>
    <span class="token keyword">const</span> value <span class="token operator">=</span> obj<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">;</span>

    <span class="token keyword">if</span> <span class="token punctuation">(</span>value<span class="token punctuation">.</span>$value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// This is a token</span>
      tokens<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">path</span><span class="token operator">:</span> fullPath<span class="token punctuation">,</span>
        <span class="token literal-property property">value</span><span class="token operator">:</span> value<span class="token punctuation">.</span>$value<span class="token punctuation">,</span>
        <span class="token literal-property property">type</span><span class="token operator">:</span> value<span class="token punctuation">.</span>$type <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
        <span class="token literal-property property">description</span><span class="token operator">:</span> value<span class="token punctuation">.</span>$description <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
        <span class="token literal-property property">category</span><span class="token operator">:</span> value<span class="token punctuation">.</span>$extensions<span class="token operator">?.</span><span class="token punctuation">[</span><span class="token string">'com.notion'</span><span class="token punctuation">]</span><span class="token operator">?.</span>category <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
        <span class="token literal-property property">status</span><span class="token operator">:</span> value<span class="token punctuation">.</span>$extensions<span class="token operator">?.</span><span class="token punctuation">[</span><span class="token string">'com.notion'</span><span class="token punctuation">]</span><span class="token operator">?.</span>status <span class="token operator">||</span> <span class="token string">'Draft'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">notionId</span><span class="token operator">:</span> value<span class="token punctuation">.</span>$extensions<span class="token operator">?.</span><span class="token punctuation">[</span><span class="token string">'com.notion'</span><span class="token punctuation">]</span><span class="token operator">?.</span>notionId <span class="token operator">||</span> <span class="token keyword">null</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">'object'</span> <span class="token operator">&amp;&amp;</span> value <span class="token operator">!==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// Recurse for nested objects</span>
      tokens<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token function">flattenTokens</span><span class="token punctuation">(</span>value<span class="token punctuation">,</span> fullPath<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> tokens<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Finally, the main sync function that orchestrates everything:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">/**
 * Main function to sync tokens from Notion
 */</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">syncTokens</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'🔄 Fetching tokens from Notion...'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> pages <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetchTokensFromNotion</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">✅ Found </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>pages<span class="token punctuation">.</span>length<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> approved tokens\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> notionTokens <span class="token operator">=</span> pages<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>extractTokenData<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> newTokenTree <span class="token operator">=</span> <span class="token function">buildTokenTree</span><span class="token punctuation">(</span>notionTokens<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Create tokens directory if it doesn't exist</span>
  <span class="token keyword">const</span> tokensDir <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'tokens'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>fs<span class="token punctuation">.</span><span class="token function">existsSync</span><span class="token punctuation">(</span>tokensDir<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    fs<span class="token punctuation">.</span><span class="token function">mkdirSync</span><span class="token punctuation">(</span>tokensDir<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token literal-property property">recursive</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// Check for conflicts with existing tokens.json</span>
  <span class="token keyword">const</span> outputPath <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>tokensDir<span class="token punctuation">,</span> <span class="token string">'tokens.json'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">let</span> existingTokens <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token keyword">let</span> conflicts <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

  <span class="token keyword">if</span> <span class="token punctuation">(</span>fs<span class="token punctuation">.</span><span class="token function">existsSync</span><span class="token punctuation">(</span>outputPath<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">try</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> existingData <span class="token operator">=</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span>outputPath<span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      existingTokens <span class="token operator">=</span> <span class="token function">flattenTokens</span><span class="token punctuation">(</span>existingData<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      console<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span>
        <span class="token string">'⚠️  Could not read existing tokens.json, treating as new file\n'</span>
      <span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// Flatten new tokens for comparison</span>
  <span class="token keyword">const</span> flatNewTokens <span class="token operator">=</span> <span class="token function">flattenTokens</span><span class="token punctuation">(</span>newTokenTree<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Check for conflicts (token exists in both but with different values)</span>
  flatNewTokens<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">newToken</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> existing <span class="token operator">=</span> existingTokens<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">t</span><span class="token punctuation">)</span> <span class="token operator">=></span> t<span class="token punctuation">.</span>path <span class="token operator">===</span> newToken<span class="token punctuation">.</span>path<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>existing <span class="token operator">&amp;&amp;</span> existing<span class="token punctuation">.</span>value <span class="token operator">!==</span> newToken<span class="token punctuation">.</span>value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      conflicts<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">path</span><span class="token operator">:</span> newToken<span class="token punctuation">.</span>path<span class="token punctuation">,</span>
        <span class="token literal-property property">local</span><span class="token operator">:</span> existing<span class="token punctuation">.</span>value<span class="token punctuation">,</span>
        <span class="token literal-property property">notion</span><span class="token operator">:</span> newToken<span class="token punctuation">.</span>value<span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Report what we found</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>conflicts<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>
      <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">⚠️  Found </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>conflicts<span class="token punctuation">.</span>length<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> conflicts (local changes != Notion):</span><span class="token template-punctuation string">`</span></span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
    conflicts<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">conflict</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">   </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>conflict<span class="token punctuation">.</span>path<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">:</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">     Local: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>conflict<span class="token punctuation">.</span>local<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">     Notion: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>conflict<span class="token punctuation">.</span>notion<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">\nSyncing from Notion (Notion values take precedence)\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// Write tokens to JSON file (Notion is source of truth)</span>
  fs<span class="token punctuation">.</span><span class="token function">writeFileSync</span><span class="token punctuation">(</span>outputPath<span class="token punctuation">,</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>newTokenTree<span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">💾 Tokens saved to </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>outputPath<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'✨ Sync complete!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> newTokenTree<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// Run if called directly</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">import</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>url <span class="token operator">===</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">file://</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>process<span class="token punctuation">.</span>argv<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">syncTokens</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>error<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">export</span> <span class="token punctuation">{</span> syncTokens <span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>What the sync script does:</p>
<ol>
<li><strong>Fetches approved tokens</strong> from your Notion database</li>
<li><strong>Compares with existing tokens.json</strong> to detect conflicts</li>
<li><strong>Reports any differences</strong>: If you've edited a token locally and it changed in Notion, you'll see a warning</li>
<li><strong>Syncs from Notion</strong>: Notion is always the source of truth, so the Notion values win</li>
<li><strong>Preserves metadata</strong>: Keeps the <code>$extensions</code> and Notion IDs for future syncs and pushes</li>
</ol>
<figure class="at-c-figure--article-image at-g-popout">
  <img 
    src="/images/articles/notion/sync-script-terminal-output.jpg" 
    alt="Sync script terminal output"
    loading="lazy"
  >
  <figcaption>Terminal output showing the successful execution of the sync script. The display includes emoji indicators for different stages, conflict detection and resolution messaging, and final confirmation with indicators.</figcaption>
</figure>
<p>This way you know exactly what changed and won't be surprised by overwritten values.</p>
<h2 id="integrating-with-style-dictionary" tabindex="-1">Integrating With Style Dictionary</h2>
<p>Once tokens are syncing from Notion, create a <code>build.js</code> file that runs Style Dictionary to generate platform-specific files.</p>
<p>First, set up the imports and environment:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> fs <span class="token keyword">from</span> <span class="token string">'fs'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> path <span class="token keyword">from</span> <span class="token string">'path'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> fileURLToPath <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'url'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> dotenv <span class="token keyword">from</span> <span class="token string">'dotenv'</span><span class="token punctuation">;</span>

dotenv<span class="token punctuation">.</span><span class="token function">config</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> __filename <span class="token operator">=</span> <span class="token function">fileURLToPath</span><span class="token punctuation">(</span><span class="token keyword">import</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> __dirname <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">dirname</span><span class="token punctuation">(</span>__filename<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> notionDatabaseId <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NOTION_DATABASE_ID</span><span class="token punctuation">;</span></code></pre>
<p>This function adds a header comment to generated files with Notion metadata:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">/**
 * Add Notion metadata comment to generated files
 */</span>
<span class="token keyword">function</span> <span class="token function">addNotionHeader</span><span class="token punctuation">(</span><span class="token parameter">filePath</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> notionUrl <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">https://www.notion.so/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>notionDatabaseId<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> header <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">/**
 * Do not edit directly, this file was auto-generated.
 * 
 * Generated from Notion Design Tokens
 * Database: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>notionUrl<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">
 * Last updated: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toISOString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">
 */\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> content <span class="token operator">=</span> fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span>filePath<span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> lines <span class="token operator">=</span> content<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Remove all comment blocks at the top of the file</span>
  <span class="token keyword">let</span> contentStartIndex <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
  <span class="token keyword">let</span> inComment <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>

  <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> lines<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>lines<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'/**'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      inComment <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>inComment <span class="token operator">&amp;&amp;</span> lines<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'*/'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      contentStartIndex <span class="token operator">=</span> i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span>
      <span class="token comment">// Skip empty lines after comment</span>
      <span class="token keyword">while</span> <span class="token punctuation">(</span>
        contentStartIndex <span class="token operator">&lt;</span> lines<span class="token punctuation">.</span>length <span class="token operator">&amp;&amp;</span>
        lines<span class="token punctuation">[</span>contentStartIndex<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token string">''</span>
      <span class="token punctuation">)</span> <span class="token punctuation">{</span>
        contentStartIndex<span class="token operator">++</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      <span class="token keyword">break</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">const</span> newContent <span class="token operator">=</span>
    header <span class="token operator">+</span> lines<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span>contentStartIndex<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">trimStart</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  fs<span class="token punctuation">.</span><span class="token function">writeFileSync</span><span class="token punctuation">(</span>filePath<span class="token punctuation">,</span> newContent<span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>The main build function runs Style Dictionary to generate platform files:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'🏗️  Building with Style Dictionary...\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Configure Style Dictionary</span>
  <span class="token keyword">const</span> sd <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'tokens/**/*.json'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
          <span class="token punctuation">{</span>
            <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'variables.css'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token literal-property property">scss</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'scss'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/scss/'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
          <span class="token punctuation">{</span>
            <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'_variables.scss'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'scss/variables'</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token literal-property property">js</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'js'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/js/'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
          <span class="token punctuation">{</span>
            <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'tokens.js'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'javascript/es6'</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Build all platforms</span>
  <span class="token keyword">await</span> sd<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Add Notion metadata to generated files</span>
  <span class="token function">addNotionHeader</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'build/css/variables.css'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">addNotionHeader</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'build/scss/_variables.scss'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'\n✅ Build complete!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>error<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<figure class="at-c-figure--article-image at-g-popout">
  <img 
    src="/images/articles/notion/build-script-terminal-output.jpg" 
    alt="Terminal window showing successful Style Dictionary build output with checkmarks for CSS, SCSS, and JS files"
    loading="lazy"
  >
  <figcaption>Build script terminal output showing the successful completion of the Style Dictionary build process.</figcaption>
</figure>
<h2 id="adding-advanced-features" tabindex="-1">Adding Advanced Features</h2>
<p>Once the basic workflow is in place, consider these optional enhancements:</p>
<h3 id="organizing-by-category" tabindex="-1">Organizing by Category</h3>
<p>If you want to keep tokens organised by category (which can be useful with large token sets):</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">syncTokensByCategory</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> pages <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetchTokensFromNotion</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> tokens <span class="token operator">=</span> pages<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>extractTokenData<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Group by category</span>
  <span class="token keyword">const</span> categories <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
  tokens<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> category <span class="token operator">=</span> token<span class="token punctuation">.</span>category <span class="token operator">||</span> <span class="token string">'general'</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>categories<span class="token punctuation">[</span>category<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      categories<span class="token punctuation">[</span>category<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    categories<span class="token punctuation">[</span>category<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Write separate files per category</span>
  <span class="token keyword">const</span> tokensDir <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'tokens'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>fs<span class="token punctuation">.</span><span class="token function">existsSync</span><span class="token punctuation">(</span>tokensDir<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    fs<span class="token punctuation">.</span><span class="token function">mkdirSync</span><span class="token punctuation">(</span>tokensDir<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token literal-property property">recursive</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>categories<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">category</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> tree <span class="token operator">=</span> <span class="token function">buildTokenTree</span><span class="token punctuation">(</span>categories<span class="token punctuation">[</span>category<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> outputPath <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>tokensDir<span class="token punctuation">,</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>category<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.json</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    fs<span class="token punctuation">.</span><span class="token function">writeFileSync</span><span class="token punctuation">(</span>outputPath<span class="token punctuation">,</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>tree<span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">💾 </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>category<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> tokens saved to </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>outputPath<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="validating-token-data" tabindex="-1">Validating Token Data</h3>
<p>Add basic validation to catch issues early, invalid color values, malformed dimensions, and other data problems:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">function</span> <span class="token function">validateToken</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> errors <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>token<span class="token punctuation">.</span>path<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    errors<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token string">'Missing token path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>token<span class="token punctuation">.</span>value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    errors<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token string">'Missing token value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>token<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    errors<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token string">'Missing token type'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// Validate color format</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>token<span class="token punctuation">.</span>type <span class="token operator">===</span> <span class="token string">'color'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> hexPattern <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>hexPattern<span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>token<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      errors<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Invalid color format: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// Validate dimension format</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>token<span class="token punctuation">.</span>type <span class="token operator">===</span> <span class="token string">'dimension'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> dimensionPattern <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\d+(\.\d+)?(px|rem|em|%)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>dimensionPattern<span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>token<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      errors<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Invalid dimension format: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">return</span> errors<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// Use in extractTokenData</span>
<span class="token keyword">function</span> <span class="token function">extractTokenData</span><span class="token punctuation">(</span><span class="token parameter">page</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> properties <span class="token operator">=</span> page<span class="token punctuation">.</span>properties<span class="token punctuation">;</span>

  <span class="token keyword">const</span> token <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">id</span><span class="token operator">:</span> page<span class="token punctuation">.</span>id<span class="token punctuation">,</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span> properties<span class="token punctuation">.</span>Name<span class="token operator">?.</span>title<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">?.</span>plain_text <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
    <span class="token literal-property property">path</span><span class="token operator">:</span> properties<span class="token punctuation">[</span><span class="token string">'Token Path'</span><span class="token punctuation">]</span><span class="token operator">?.</span>rich_text<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">?.</span>plain_text <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
    <span class="token literal-property property">value</span><span class="token operator">:</span> properties<span class="token punctuation">.</span>Value<span class="token operator">?.</span>rich_text<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">?.</span>plain_text <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
    <span class="token literal-property property">type</span><span class="token operator">:</span> properties<span class="token punctuation">.</span>Type<span class="token operator">?.</span>select<span class="token operator">?.</span>name <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
    <span class="token literal-property property">category</span><span class="token operator">:</span> properties<span class="token punctuation">.</span>Category<span class="token operator">?.</span>select<span class="token operator">?.</span>name <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
    <span class="token literal-property property">status</span><span class="token operator">:</span> properties<span class="token punctuation">.</span>Status<span class="token operator">?.</span>select<span class="token operator">?.</span>name <span class="token operator">||</span> <span class="token string">'Draft'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">description</span><span class="token operator">:</span> properties<span class="token punctuation">.</span>Description<span class="token operator">?.</span>rich_text<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">?.</span>plain_text <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> errors <span class="token operator">=</span> <span class="token function">validateToken</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>errors<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">⚠️  Validation errors for "</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">":</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> errors<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">return</span> token<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="using-token-references" tabindex="-1">Using Token References</h3>
<p>One feature I find useful is the ability to reference other tokens. So if you want one token to use the value of another:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">function</span> <span class="token function">buildTokenTree</span><span class="token punctuation">(</span><span class="token parameter">tokens</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> tree <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>

  tokens<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> pathParts <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">'.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">let</span> current <span class="token operator">=</span> tree<span class="token punctuation">;</span>

    pathParts<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">part<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>index <span class="token operator">===</span> pathParts<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// Check if value is a reference (starts with {)</span>
        <span class="token keyword">const</span> isReference <span class="token operator">=</span>
          token<span class="token punctuation">.</span>value<span class="token punctuation">.</span><span class="token function">startsWith</span><span class="token punctuation">(</span><span class="token string">'{'</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>value<span class="token punctuation">.</span><span class="token function">endsWith</span><span class="token punctuation">(</span><span class="token string">'}'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        current<span class="token punctuation">[</span>part<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">value</span><span class="token operator">:</span> isReference <span class="token operator">?</span> token<span class="token punctuation">.</span>value <span class="token operator">:</span> token<span class="token punctuation">.</span>value<span class="token punctuation">,</span>
          <span class="token literal-property property">$type</span><span class="token operator">:</span> token<span class="token punctuation">.</span>type<span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span>token<span class="token punctuation">.</span>description<span class="token punctuation">)</span> <span class="token punctuation">{</span>
          current<span class="token punctuation">[</span>part<span class="token punctuation">]</span><span class="token punctuation">.</span>$description <span class="token operator">=</span> token<span class="token punctuation">.</span>description<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>current<span class="token punctuation">[</span>part<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          current<span class="token punctuation">[</span>part<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        current <span class="token operator">=</span> current<span class="token punctuation">[</span>part<span class="token punctuation">]</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> tree<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>In your Notion database, you can now use references like:</p>
<ul>
<li>Value: <code>{color.brand.primary}</code></li>
</ul>
<p>Style Dictionary will automatically resolve these references during the build process.</p>
<h3 id="preserving-notion-metadata-with-%24extensions" tabindex="-1">Preserving Notion Metadata With $extensions</h3>
<p>Keep Notion metadata in your generated JSON files using the Design Tokens <code>$extensions</code> field, which is designed specifically for custom metadata.</p>
<p>The sync script includes this by default, each token gets an <code>$extensions</code> object that tracks:</p>
<ul>
<li><strong>status</strong>: Whether the token is Draft, Review, Approved, or Deprecated</li>
<li><strong>category</strong>: How the token is grouped</li>
<li><strong>notionId</strong>: The unique ID of the Notion page (useful for linking back)</li>
<li><strong>lastSynced</strong>: When the token was last pulled from Notion</li>
</ul>
<p>This means your generated JSON looks like this:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#007bff"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Primary brand color"</span><span class="token punctuation">,</span>
      <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"com.notion"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"status"</span><span class="token operator">:</span> <span class="token string">"Approved"</span><span class="token punctuation">,</span>
          <span class="token property">"category"</span><span class="token operator">:</span> <span class="token string">"brand"</span><span class="token punctuation">,</span>
          <span class="token property">"notionId"</span><span class="token operator">:</span> <span class="token string">"a1b2c3d4e5f6g7h8"</span><span class="token punctuation">,</span>
          <span class="token property">"lastSynced"</span><span class="token operator">:</span> <span class="token string">"2026-02-09T10:30:00.000Z"</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>This metadata is useful for:</p>
<ul>
<li><strong>Audit trails</strong>: Track exactly when tokens changed and what their approval status was</li>
<li><strong>Debugging</strong>: Identify which Notion page a token came from without confusion</li>
<li><strong>Automation</strong>: Use the extension data in custom Style Dictionary transforms or other tools</li>
<li><strong>Documentation</strong>: Generated files become self-documenting with full context</li>
</ul>
<p>The <code>$extensions</code> field is optional, Style Dictionary and other tools treat it as optional metadata and work fine without it. For complex workflows or full audit trail tracking in version control, it's worth preserving.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>If you want to dive deeper into the <code>$extensions</code> specification and see real-world examples, check out my post <a href="https://www.alwaystwisted.com/articles/understanding-extensions-in-the-design-tokens-spec">Understanding $extensions in the Design Tokens Specification</a> and the <a href="https://www.alwaystwisted.com/projects/dtm/extensions/">Design Tokens Extensions Explorer</a> tool.</p>
</div>
<h2 id="updating-your-package.json" tabindex="-1">Updating Your package.json</h2>
<p>Add helpful scripts to your <code>package.json</code> for managing the workflow:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"design-tokens"</span><span class="token punctuation">,</span>
  <span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"1.0.0"</span><span class="token punctuation">,</span>
  <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"module"</span><span class="token punctuation">,</span>
  <span class="token property">"scripts"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"sync"</span><span class="token operator">:</span> <span class="token string">"node fetch-tokens.js"</span><span class="token punctuation">,</span>
    <span class="token property">"push"</span><span class="token operator">:</span> <span class="token string">"node push-tokens.js"</span><span class="token punctuation">,</span>
    <span class="token property">"build"</span><span class="token operator">:</span> <span class="token string">"node build.js"</span><span class="token punctuation">,</span>
    <span class="token property">"sync:build"</span><span class="token operator">:</span> <span class="token string">"npm run sync &amp;&amp; npm run build"</span><span class="token punctuation">,</span>
    <span class="token property">"watch"</span><span class="token operator">:</span> <span class="token string">"nodemon --watch tokens -e json --exec npm run build"</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"devDependencies"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"@notionhq/client"</span><span class="token operator">:</span> <span class="token string">"^2.2.15"</span><span class="token punctuation">,</span>
    <span class="token property">"style-dictionary"</span><span class="token operator">:</span> <span class="token string">"^4.1.4"</span><span class="token punctuation">,</span>
    <span class="token property">"dotenv"</span><span class="token operator">:</span> <span class="token string">"^16.3.1"</span><span class="token punctuation">,</span>
    <span class="token property">"nodemon"</span><span class="token operator">:</span> <span class="token string">"^3.0.0"</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>This enables the following commands:</p>
<ul>
<li><code>npm run sync</code> - Fetch tokens from Notion</li>
<li><code>npm run push</code> - Push changes from JSON back to Notion</li>
<li><code>npm run build</code> - Build with Style Dictionary (without syncing)</li>
<li><code>npm run sync:build</code> - Sync tokens AND build (combined operation)</li>
<li><code>npm run watch</code> - Watch for token changes and rebuild</li>
</ul>
<h2 id="two-way-sync%3A-going-the-other-direction" tabindex="-1">Two-Way Sync: Going the Other Direction</h2>
<p>This workflow supports bidirectional syncing, pull tokens from Notion into your JSON, or push changes from your JSON back to Notion for team review.</p>
<p>Create a <code>push-tokens.js</code> script to enable pushing.</p>
<p>First, set up the imports and initialise the Notion client:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> Client <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@notionhq/client'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> fs <span class="token keyword">from</span> <span class="token string">'fs'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> path <span class="token keyword">from</span> <span class="token string">'path'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> fileURLToPath <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'url'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> dotenv <span class="token keyword">from</span> <span class="token string">'dotenv'</span><span class="token punctuation">;</span>

dotenv<span class="token punctuation">.</span><span class="token function">config</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> __filename <span class="token operator">=</span> <span class="token function">fileURLToPath</span><span class="token punctuation">(</span><span class="token keyword">import</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> __dirname <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">dirname</span><span class="token punctuation">(</span>__filename<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> notion <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Client</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">auth</span><span class="token operator">:</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NOTION_TOKEN</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> databaseId <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NOTION_DATABASE_ID</span><span class="token punctuation">;</span></code></pre>
<p>This function flattens the nested token structure back into an array for processing. It's the inverse of the buildTokenTree function:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">/**
 * Flatten nested token object into array for processing
 * This converts the hierarchical JSON structure back to a flat array
 */</span>
<span class="token keyword">function</span> <span class="token function">flattenTokens</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> prefix <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> tokens <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

  Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">key</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> fullPath <span class="token operator">=</span> prefix <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>prefix<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>key<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> key<span class="token punctuation">;</span>
    <span class="token keyword">const</span> value <span class="token operator">=</span> obj<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">;</span>

    <span class="token keyword">if</span> <span class="token punctuation">(</span>value<span class="token punctuation">.</span>$value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// This is a token leaf node</span>
      tokens<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">path</span><span class="token operator">:</span> fullPath<span class="token punctuation">,</span>
        <span class="token literal-property property">value</span><span class="token operator">:</span> value<span class="token punctuation">.</span>$value<span class="token punctuation">,</span>
        <span class="token literal-property property">type</span><span class="token operator">:</span> value<span class="token punctuation">.</span>$type <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
        <span class="token literal-property property">description</span><span class="token operator">:</span> value<span class="token punctuation">.</span>$description <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
        <span class="token literal-property property">category</span><span class="token operator">:</span> value<span class="token punctuation">.</span>$extensions<span class="token operator">?.</span><span class="token punctuation">[</span><span class="token string">'com.notion'</span><span class="token punctuation">]</span><span class="token operator">?.</span>category <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
        <span class="token literal-property property">status</span><span class="token operator">:</span> value<span class="token punctuation">.</span>$extensions<span class="token operator">?.</span><span class="token punctuation">[</span><span class="token string">'com.notion'</span><span class="token punctuation">]</span><span class="token operator">?.</span>status <span class="token operator">||</span> <span class="token string">'Draft'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">notionId</span><span class="token operator">:</span> value<span class="token punctuation">.</span>$extensions<span class="token operator">?.</span><span class="token punctuation">[</span><span class="token string">'com.notion'</span><span class="token punctuation">]</span><span class="token operator">?.</span>notionId <span class="token operator">||</span> <span class="token keyword">null</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">'object'</span> <span class="token operator">&amp;&amp;</span> value <span class="token operator">!==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// Recurse for nested objects (branches)</span>
      tokens<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token function">flattenTokens</span><span class="token punctuation">(</span>value<span class="token punctuation">,</span> fullPath<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> tokens<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This function updates an existing Notion page with new token values:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">/**
 * Update an existing Notion page with new token data
 * Only updates the fields that can be modified (value, type, category, description)
 */</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">updateNotionPage</span><span class="token punctuation">(</span><span class="token parameter">pageId<span class="token punctuation">,</span> token</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
    <span class="token keyword">await</span> notion<span class="token punctuation">.</span>pages<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      <span class="token literal-property property">page_id</span><span class="token operator">:</span> pageId<span class="token punctuation">,</span>
      <span class="token literal-property property">properties</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">Value</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">rich_text</span><span class="token operator">:</span> <span class="token punctuation">[</span>
            <span class="token punctuation">{</span>
              <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'text'</span><span class="token punctuation">,</span>
              <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">content</span><span class="token operator">:</span> token<span class="token punctuation">.</span>value <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token literal-property property">Type</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">select</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">name</span><span class="token operator">:</span> token<span class="token punctuation">.</span>type <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token literal-property property">Category</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">select</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">name</span><span class="token operator">:</span> token<span class="token punctuation">.</span>category <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token literal-property property">Description</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">rich_text</span><span class="token operator">:</span> <span class="token punctuation">[</span>
            <span class="token punctuation">{</span>
              <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'text'</span><span class="token punctuation">,</span>
              <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">content</span><span class="token operator">:</span> token<span class="token punctuation">.</span>description <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  ❌ Failed to update "</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>path<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">":</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> error<span class="token punctuation">.</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>This function creates a new Notion page for tokens that don't exist yet:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">/**
 * Create a new Notion page in the database for a new token
 * New tokens are created with "Draft" status for review
 */</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">createNotionPage</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
    <span class="token keyword">await</span> notion<span class="token punctuation">.</span>pages<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      <span class="token literal-property property">parent</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">database_id</span><span class="token operator">:</span> databaseId <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token literal-property property">properties</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">Name</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">title</span><span class="token operator">:</span> <span class="token punctuation">[</span>
            <span class="token punctuation">{</span>
              <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'text'</span><span class="token punctuation">,</span>
              <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">content</span><span class="token operator">:</span> token<span class="token punctuation">.</span>path <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token string-property property">'Token Path'</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">rich_text</span><span class="token operator">:</span> <span class="token punctuation">[</span>
            <span class="token punctuation">{</span>
              <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'text'</span><span class="token punctuation">,</span>
              <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">content</span><span class="token operator">:</span> token<span class="token punctuation">.</span>path <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token literal-property property">Value</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">rich_text</span><span class="token operator">:</span> <span class="token punctuation">[</span>
            <span class="token punctuation">{</span>
              <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'text'</span><span class="token punctuation">,</span>
              <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">content</span><span class="token operator">:</span> token<span class="token punctuation">.</span>value <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token literal-property property">Type</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">select</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">name</span><span class="token operator">:</span> token<span class="token punctuation">.</span>type <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token literal-property property">Category</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">select</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">name</span><span class="token operator">:</span> token<span class="token punctuation">.</span>category <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token literal-property property">Description</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">rich_text</span><span class="token operator">:</span> <span class="token punctuation">[</span>
            <span class="token punctuation">{</span>
              <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'text'</span><span class="token punctuation">,</span>
              <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">content</span><span class="token operator">:</span> token<span class="token punctuation">.</span>description <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token literal-property property">Status</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">select</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'Draft'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token comment">// New tokens start as drafts</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  ❌ Failed to create "</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>path<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">":</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> error<span class="token punctuation">.</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>This function fetches all existing tokens from Notion to compare against local changes:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">/**
 * Fetch all tokens currently in Notion database
 * Returns a map of token path -> Notion data for quick lookup
 * This is used to determine what exists in Notion vs. what we want to push
 */</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fetchExistingTokensFromNotion</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> allPages <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token keyword">let</span> hasMore <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
    <span class="token keyword">let</span> startCursor <span class="token operator">=</span> <span class="token keyword">undefined</span><span class="token punctuation">;</span>

    <span class="token comment">// Fetch all pages from database (not only approved ones)</span>
    <span class="token keyword">while</span> <span class="token punctuation">(</span>hasMore<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token keyword">await</span> notion<span class="token punctuation">.</span>databases<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">database_id</span><span class="token operator">:</span> databaseId<span class="token punctuation">,</span>
        <span class="token literal-property property">start_cursor</span><span class="token operator">:</span> startCursor<span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

      allPages <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">...</span>allPages<span class="token punctuation">,</span> <span class="token operator">...</span>response<span class="token punctuation">.</span>results<span class="token punctuation">]</span><span class="token punctuation">;</span>
      hasMore <span class="token operator">=</span> response<span class="token punctuation">.</span>has_more<span class="token punctuation">;</span>
      startCursor <span class="token operator">=</span> response<span class="token punctuation">.</span>next_cursor<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// Build lookup map of token path -> Notion data for fast comparison</span>
    <span class="token keyword">const</span> notionTokens <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>

    allPages<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">page</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> props <span class="token operator">=</span> page<span class="token punctuation">.</span>properties<span class="token punctuation">;</span>
      <span class="token keyword">const</span> tokenPath <span class="token operator">=</span> props<span class="token punctuation">[</span><span class="token string">'Token Path'</span><span class="token punctuation">]</span><span class="token operator">?.</span>rich_text<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">?.</span>plain_text<span class="token punctuation">;</span>

      <span class="token keyword">if</span> <span class="token punctuation">(</span>tokenPath<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        notionTokens<span class="token punctuation">[</span>tokenPath<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">id</span><span class="token operator">:</span> page<span class="token punctuation">.</span>id<span class="token punctuation">,</span>
          <span class="token literal-property property">value</span><span class="token operator">:</span> props<span class="token punctuation">.</span>Value<span class="token operator">?.</span>rich_text<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">?.</span>plain_text <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
          <span class="token literal-property property">type</span><span class="token operator">:</span> props<span class="token punctuation">.</span>Type<span class="token operator">?.</span>select<span class="token operator">?.</span>name <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
          <span class="token literal-property property">description</span><span class="token operator">:</span> props<span class="token punctuation">.</span>Description<span class="token operator">?.</span>rich_text<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">?.</span>plain_text <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
          <span class="token literal-property property">category</span><span class="token operator">:</span> props<span class="token punctuation">.</span>Category<span class="token operator">?.</span>select<span class="token operator">?.</span>name <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> notionTokens<span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">'Error fetching from Notion:'</span><span class="token punctuation">,</span> error<span class="token punctuation">.</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">throw</span> error<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>This function compares local tokens with Notion versions to detect changes:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">/**
 * Compare local token with Notion version to detect changes
 * Returns true if the token needs to be updated in Notion
 */</span>
<span class="token keyword">function</span> <span class="token function">hasTokenChanged</span><span class="token punctuation">(</span><span class="token parameter">local<span class="token punctuation">,</span> notion</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>notion<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token comment">// New token (doesn't exist in Notion yet)</span>

  <span class="token comment">// Check if any of the key properties differ</span>
  <span class="token keyword">return</span> <span class="token punctuation">(</span>
    local<span class="token punctuation">.</span>value <span class="token operator">!==</span> notion<span class="token punctuation">.</span>value <span class="token operator">||</span>
    local<span class="token punctuation">.</span>type <span class="token operator">!==</span> notion<span class="token punctuation">.</span>type <span class="token operator">||</span>
    local<span class="token punctuation">.</span>description <span class="token operator">!==</span> notion<span class="token punctuation">.</span>description <span class="token operator">||</span>
    local<span class="token punctuation">.</span>category <span class="token operator">!==</span> notion<span class="token punctuation">.</span>category
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Finally, the main push function that orchestrates the entire process:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">/**
 * Main function to push tokens to Notion
 * This implements a "smart sync" that only updates what has changed
 */</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">pushTokens</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'📤 Pushing tokens to Notion...\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Read current tokens from JSON</span>
  <span class="token keyword">const</span> tokensPath <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'tokens'</span><span class="token punctuation">,</span> <span class="token string">'tokens.json'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>fs<span class="token punctuation">.</span><span class="token function">existsSync</span><span class="token punctuation">(</span>tokensPath<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">'❌ tokens/tokens.json not found. Run "npm run sync" first.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    process<span class="token punctuation">.</span><span class="token function">exit</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">const</span> tokensData <span class="token operator">=</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span>tokensPath<span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> localTokens <span class="token operator">=</span> <span class="token function">flattenTokens</span><span class="token punctuation">(</span>tokensData<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Fetch current state from Notion for comparison</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'🔍 Checking Notion database for existing tokens...\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> notionTokens <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetchExistingTokensFromNotion</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Categorise tokens: new, changed, or unchanged</span>
  <span class="token keyword">const</span> changedTokens <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> newTokens <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> unchangedTokens <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

  localTokens<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> notionToken <span class="token operator">=</span> notionTokens<span class="token punctuation">[</span>token<span class="token punctuation">.</span>path<span class="token punctuation">]</span><span class="token punctuation">;</span>

    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>notionToken<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// Token doesn't exist in Notion yet</span>
      newTokens<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">hasTokenChanged</span><span class="token punctuation">(</span>token<span class="token punctuation">,</span> notionToken<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// Token exists but has different values - needs update</span>
      token<span class="token punctuation">.</span>notionId <span class="token operator">=</span> notionToken<span class="token punctuation">.</span>id<span class="token punctuation">;</span> <span class="token comment">// Store ID for updating</span>
      changedTokens<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      <span class="token comment">// Token exists and is identical</span>
      unchangedTokens<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Report what we found</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Found </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>localTokens<span class="token punctuation">.</span>length<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> tokens total:</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  • </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>unchangedTokens<span class="token punctuation">.</span>length<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> unchanged (skipping)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  • </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>changedTokens<span class="token punctuation">.</span>length<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> changed</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  • </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>newTokens<span class="token punctuation">.</span>length<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> new\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Exit early if nothing to do</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>changedTokens<span class="token punctuation">.</span>length <span class="token operator">===</span> <span class="token number">0</span> <span class="token operator">&amp;&amp;</span> newTokens<span class="token punctuation">.</span>length <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Everything is already synced! Nothing to do.\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// Push changes to Notion</span>
  <span class="token keyword">let</span> updated <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
  <span class="token keyword">let</span> created <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>

  <span class="token comment">// Update existing tokens</span>
  <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">const</span> token <span class="token keyword">of</span> changedTokens<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    process<span class="token punctuation">.</span>stdout<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Updating "</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>path<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">"... </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">await</span> <span class="token function">updateNotionPage</span><span class="token punctuation">(</span>token<span class="token punctuation">.</span>notionId<span class="token punctuation">,</span> token<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'✅'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      updated<span class="token operator">++</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// Create new tokens</span>
  <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">const</span> token <span class="token keyword">of</span> newTokens<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    process<span class="token punctuation">.</span>stdout<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Creating "</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>path<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">"... </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">await</span> <span class="token function">createNotionPage</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'✅'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      created<span class="token operator">++</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">\n✅ Push complete!</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">   Updated: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>updated<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> tokens</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">   Created: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>created<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> new tokens</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">export</span> <span class="token punctuation">{</span> pushTokens <span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<figure class="at-c-figure--article-image at-g-popout">
  <img 
    src="/images/articles/notion/push-script-terminal-output.jpg" 
    alt="Push script terminal output"
    loading="lazy"
  >
  <figcaption>Terminal output showing the successful execution of the push script, including token updates and creations with progress indicators.</figcaption>
</figure>
<p>How this works:</p>
<ol>
<li><strong>Fetches from Notion</strong>: Queries the entire database to get current token state</li>
<li><strong>Builds a lookup map</strong>: Creates a fast dictionary of token path → current values</li>
<li><strong>Compares local vs. Notion</strong>: For each local token, checks if value, type, category, or description differs</li>
<li><strong>Only updates what changed</strong>: Only makes API calls for tokens that actually differ</li>
<li><strong>No hidden files</strong>: Everything is tracked by comparing against the live Notion database</li>
</ol>
<p><strong>This approach is better because:</strong></p>
<ul>
<li>No hidden <code>.lastPushed.json</code> files to manage</li>
<li>Single source of truth is always Notion</li>
<li>Works even if you skip a push or run the script multiple times</li>
<li>Transparent, you can see exactly what's different</li>
<li>Safe, only touches tokens that actually changed</li>
</ul>
<p>How it works:</p>
<ol>
<li><strong>Reads your JSON</strong>: Parses <code>tokens/tokens.json</code> and flattens the nested structure</li>
<li><strong>Matches tokens</strong>: Uses the <code>notionId</code> stored in <code>$extensions</code> to find which Notion page to update</li>
<li><strong>Updates or creates</strong>: For existing tokens, updates their values; for new ones, creates new Notion pages (marked as &quot;Draft&quot;)</li>
<li><strong>Preserves metadata</strong>: Keeps category, status, and description synced</li>
</ol>
<p>This is especially useful when:</p>
<ul>
<li>A developer tweaks a token value and wants that change reflected in Notion</li>
<li>You're bulk-importing tokens from another source</li>
<li>You want to automate token creation in Notion via script</li>
</ul>
<p>Run <code>npm run push</code> after editing your JSON, and the Notion database updates automatically.</p>
<h2 id="there-you-have-it!" tabindex="-1">There you have it!</h2>
<p>We've created a collaborative design token workflow that helps bring everyone together. Your team can now manage tokens in Notion's friendly interface, while developers get clean JSON for their builds. Everything stays in sync from one source of truth.</p>
<p>This foundation is pretty solid and should ready for expansion. You could add validation to catch errors early, use token references to avoid repetition, or organise by categories for larger sets. Going further you could add functionality that will allow the tokens to be imported into design tools liek Figma or Penpot.</p>
<p>For the complete working example with all scripts, <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/14-notion-design-tokens">check out the GitHub repository</a>.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Underlining Links With CSS</title>
      <link href="https://www.alwaystwisted.com/articles/underlining-links-with-css.html"/>
      <updated>2026-02-08T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/underlining-links-with-css.html</id>
      <content type="html">
        <![CDATA[
        <p>Every time I need to style link underlines beyond the default browser styling, I find myself searching MDN for the same properties. I always think &quot;surely I know this by now?&quot; but then it slips my mind and off I go searching again. So, I've decided to write this down as my personal reference guide. Hopefully, it'll save you the same trip to the documentation!</p>
<p>For years, styling underlines on links meant either accepting the default look or hiding underlines entirely with <code>text-decoration: none;</code> and relying on other styling methods like borders or box-shadows to indicate interactivity. But CSS now gives us a whole set of <code>text-decoration</code> properties that let us get really specific about how our underlines should look and behave.</p>
<h2 id="the-text-decoration-properties" tabindex="-1">The Text Decoration Properties</h2>
<p>The &quot;modern approach&quot; to link underlines can use a set of individual <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration"><code>text-decoration</code> properties</a>. These properties give us granular control over every part of an underline.</p>
<p>Let's walk through each one.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>Historically, <code>text-decoration</code> let you choose the type of decoration (<code>none</code>, <code>underline</code>, <code>overline</code>, <code>line-through</code>), but you couldn't style it. The underline would always be the browser's default—solid, in the text color, with a fixed thickness. Now, with the individual <code>text-decoration</code> properties, you get control over the appearance. Using these properties with progressive enhancement ensures that all browsers should get a usable underline, while newer browsers get the enhanced styling.</p>
</div>
<h3 id="text-decoration" tabindex="-1"><code>text-decoration</code></h3>
<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration"><code>text-decoration</code></a> shorthand lets you set multiple underline properties in one declaration. For example:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">a</span> <span class="token punctuation">{</span>
  <span class="token property">text-decoration</span><span class="token punctuation">:</span> underline solid red 2px<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>In this example, we're saying: add an underline, make it solid, color it red, and give it a thickness of 2 pixels.</p>
<h3 id="text-decoration-line" tabindex="-1"><code>text-decoration-line</code></h3>
<p>Use <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-line"><code>text-decoration-line</code></a> when you want to control what type of line appears. You've got a few options beyond just <code>underline</code>:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">a</span> <span class="token punctuation">{</span>
  <span class="token property">text-decoration-line</span><span class="token punctuation">:</span> underline<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>You can also use <code>overline</code> (line above the text), <code>line-through</code> (for strikethrough), <code>none</code> (no decoration), or even combine them like <code>underline overline</code> for multiple lines.</p>
<h3 id="text-decoration-color" tabindex="-1"><code>text-decoration-color</code></h3>
<p>Want your underlines to be a different color than your text? That's where <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-color"><code>text-decoration-color</code></a> comes in.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">a</span> <span class="token punctuation">{</span>
  <span class="token property">text-decoration-line</span><span class="token punctuation">:</span> underline<span class="token punctuation">;</span>
  <span class="token property">text-decoration-color</span><span class="token punctuation">:</span> #ea215a<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This is particularly useful when you want a more subtle or contrasting underline color. For instance, you might want muted underlines on dark text that pop on hover.</p>
<h3 id="text-decoration-style" tabindex="-1"><code>text-decoration-style</code></h3>
<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-style"><code>text-decoration-style</code></a> property controls how the line is drawn. Beyond the standard <code>solid</code> line, you can make it:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">a</span> <span class="token punctuation">{</span>
  <span class="token property">text-decoration-line</span><span class="token punctuation">:</span> underline<span class="token punctuation">;</span>
  <span class="token property">text-decoration-style</span><span class="token punctuation">:</span> wavy<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>A wavy underline can add personality, or you might use dotted for a more playful feel.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>The available styles are: <code>solid</code> (default), <code>double</code>, <code>dotted</code>, <code>dashed</code>, and <code>wavy</code>.</p>
</div>
<h3 id="text-decoration-thickness" tabindex="-1"><code>text-decoration-thickness</code></h3>
<p>By default, browsers choose a thickness for underlines. But <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-thickness"><code>text-decoration-thickness</code></a> lets you be precise. You can use any length unit (px, em, rem) or percentages:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">a</span> <span class="token punctuation">{</span>
  <span class="token property">text-decoration-line</span><span class="token punctuation">:</span> underline<span class="token punctuation">;</span>
  <span class="token property">text-decoration-thickness</span><span class="token punctuation">:</span> 0.125em<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Using relative units like <code>em</code> is good here because the underline thickness can scale with the font size.</p>
<h3 id="text-underline-offset" tabindex="-1"><code>text-underline-offset</code></h3>
<p>One of the cool new properties, <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-underline-offset"><code>text-underline-offset</code></a> controls the space between your text and the underline itself. This is great for giving underlines more &quot;breathing room&quot;:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">a</span> <span class="token punctuation">{</span>
  <span class="token property">text-decoration</span><span class="token punctuation">:</span> underline<span class="token punctuation">;</span>
  <span class="token property">text-underline-offset</span><span class="token punctuation">:</span> 0.2em<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>You can also use negative values to bring the underline closer or above the baseline if you really wanted something unconventional.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>The <code>text-underline-offset</code> property only affects underlines, not overlines or line-through decorations.</p>
</div>
<h3 id="text-underline-position" tabindex="-1"><code>text-underline-position</code></h3>
<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-underline-position"><code>text-underline-position</code></a> property is mostly useful if you're working with text that has descenders (like g, j, p, q, y). By default, browsers may skip over these descenders to keep underlines readable. You can force different behaviour:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">a</span> <span class="token punctuation">{</span>
  <span class="token property">text-decoration</span><span class="token punctuation">:</span> underline<span class="token punctuation">;</span>
  <span class="token property">text-underline-position</span><span class="token punctuation">:</span> under<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>The <code>under</code> value forces the underline to sit below all the descenders, giving you a consistent baseline.</p>
<h3 id="text-decoration-skip-ink" tabindex="-1"><code>text-decoration-skip-ink</code></h3>
<p>Speaking of descenders, <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-skip-ink"><code>text-decoration-skip-ink</code></a> controls whether underlines skip over letter descenders:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">a</span> <span class="token punctuation">{</span>
  <span class="token property">text-decoration</span><span class="token punctuation">:</span> underline<span class="token punctuation">;</span>
  <span class="token property">text-decoration-skip-ink</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Most of the time, <code>auto</code> is fine, it lets the browser skip over descenders for better readability. But if you want the underline to go through everything, use <code>none</code>.</p>
<h2 id="before-you-ship" tabindex="-1">Before You Ship</h2>
<p>A couple of important things to keep in mind:</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p><code>text-underline-offset</code>, <code>text-underline-position</code>, and <code>text-decoration-skip-ink</code> are separate properties and aren't included in the <code>text-decoration</code> shorthand. If you use the shorthand, define them separately.</p>
</div>
<p>Also, when using the shorthand, one gotcha: setting <code>text-decoration</code> resets any previously set <code>text-decoration-thickness</code> unless you include the thickness value in the shorthand itself. It's easier to avoid the shorthand if you're using multiple properties.</p>
<p>Modern CSS text-decoration properties have solid support in current browsers, though some variations may need checking. Always test compatibility and think about progressive enhancement so that anyone on any browser gets as good an experience as possible.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Introducing The Design Tokens $extensions Checker</title>
      <link href="https://www.alwaystwisted.com/articles/introducing-the-extensions-checker.html"/>
      <updated>2026-02-02T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/introducing-the-extensions-checker.html</id>
      <content type="html">
        <![CDATA[
        <p>If you work with design tokens, you might find yourself needing to add an <a href="/articles/understanding-extensions-in-the-w3c-design-tokens-spec/"><code>$extensions</code></a> object for some specific use case. Then, down the line, other tools that consume your design tokens data might add their own extensions too. Before you know it, you're scrolling through nested metadata trying to figure out what extensions you actually have, who's using them, and whether you can clean anything up.</p>
<p>That's what I built the <a href="https://www.alwaystwisted.com/projects/dtm/extensions/"><strong>Design Tokens $extensions Checker</strong></a>. A quick way to see exactly what extensions are hiding in your design tokens.</p>
<!-- insert extensions-checker.jpg here -->
<p><img src="/images/articles/extensions-checker.jpg" alt="The Design Tokens Extensions Checker displaying the input data, examples of extensions, and output data highlighting the example found" loading="lazy" decoding="async"></p>
<h2 id="what-it-does" tabindex="-1">What it does</h2>
<p>Paste your design tokens data into the text area and it will extract every <code>$extensions</code> object it can find.</p>
<p>You should get:</p>
<ul>
<li>A full list of all extensions so you can see every namespace, property, and piece of metadata at a glance.</li>
<li>Clear visualisation with extensions grouped logically so you can spot patterns or duplicates.</li>
<li>Easy cleanup options that let you delete extensions individually or in bulk once you understand what you have.</li>
<li>A preview of your modified tokens showing the cleaned-up JSON ready to copy back into your workflow.</li>
</ul>
<h2 id="why-this-matters" tabindex="-1">Why this matters</h2>
<p>Here's the thing: <code>$extensions</code> is supposed to stay out of your way until you actually need it. But when you <em>do</em> need it — when you're auditing your token structure, migrating systems, or just trying to understand what metadata you're carrying around — it helps to see it all in one place.</p>
<p>Maybe there will be some PenPot data layered on top of Style Dictionary config information layered on top of team governance metadata. The JSON is valid and everything works, but visualizing it separately from the token values themselves makes it way easier to reason about.</p>
<h2 id="how-to-use-it" tabindex="-1">How to use it</h2>
<ol>
<li>Grab your design tokens JSON file and paste it into the text area.</li>
<li>Hit the Parse button to extract all extensions and display them.</li>
<li>Review what extensions you have, then delete ones you don't need individually or delete all of them at once.</li>
<li>Copy your cleaned-up tokens back, ready to use in your workflow.</li>
</ol>
<p>I created a sample tokens file so you can see what the output looks like without digging through your own files first.</p>
<h2 id="when-it's-useful" tabindex="-1">When it's useful</h2>
<p>This tool can be really useful if you're auditing what extensions you're actually using, migrating between different metadata systems, cleaning up bloated token files, or just curious what's hiding in your extensions.</p>
<p>Like <a href="/relicss">Relicss</a>, it runs entirely in your browser. Nothing gets sent anywhere. Your design tokens stay on your machine.</p>
<p><a href="/projects/dtm/extensions/">Grab it and give it a try</a>.</p>
<p>If you want to learn more about what <code>$extensions</code> can do and why they exist, check out <a href="/articles/understanding-extensions-in-the-w3c-design-tokens-spec/">Understanding $extensions in the W3C Design Tokens Spec</a>.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Understanding $extensions in the Design Tokens Specification</title>
      <link href="https://www.alwaystwisted.com/articles/understanding-extensions-in-the-design-tokens-spec.html"/>
      <updated>2026-01-30T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/understanding-extensions-in-the-design-tokens-spec.html</id>
      <content type="html">
        <![CDATA[
        <p>One of the smart things in the <a href="https://www.designtokens.org/tr/2025.10/format/">W3C Design Tokens Community Group (DRCG) Design Tokens spec</a> is how it acknowledges something simple, no standard can anticipate every use case.</p>
<p>Instead of trying to force everything into the specification, they created <code>$extensions</code>. Essentially it's a deliberate, scoped escape hatch. You can add extra data to your tokens without breaking them or polluting the standard.</p>
<h2 id="what-is-%24extensions%3F" tabindex="-1">What is <code>$extensions</code>?</h2>
<p>Think of it like this.</p>
<p>Your design tokens follow the spec strictly. But, sometimes you need to attach metadata that falls outside of it, tool-specific configuration, governance info, version history, whatever. Instead of inventing your own properties (which will create chaos), <code>$extensions</code> creates a place to put all this stuff.</p>
<p>Here's the important bit: The content of <code>$extensions</code> is completely freeform.</p>
<p>The spec doesn't validate what's inside. It can be strings, numbers, booleans, objects, whatever your use case needs. The only constraint is that it must be valid in whatever format you're using (JSON, YAML, etc.).</p>
<p>This is by design.</p>
<p>The DTCG intentionally placed almost no constraints on what can go in here, recognising that trying to anticipate every use case is foolish, if not futile.</p>
<p>You can use it for:</p>
<ul>
<li>Tool-specific configuration: Figma sync IDs, Style Dictionary transforms</li>
<li>Team metadata: who owns this token, approval status, links to docs</li>
<li>Workflow annotations: version history, changelog, deprecation warnings</li>
<li>Experimental features: anything not yet standardised</li>
<li>Integration data: bridges between tools, AI metadata, accessibility info</li>
</ul>
<p>One key rule? Use reverse domain notation. Instead of <code>myData</code> or <code>myData.mySite.com</code>, use <code>com.yourcompany.featureName</code>. This eliminates naming collisions and keeps things organised.</p>
<h2 id="why-this-matters" tabindex="-1">Why this matters</h2>
<p>Without something like <code>$extensions</code>, teams could be tempted to just add custom metadata at the token level. You would see things like <code>_figmaId</code>, <code>vendor-config</code>, <code>customData</code> scattered through your token files.</p>
<p>It would be a mess.</p>
<p>With <code>$extensions</code>:</p>
<ol>
<li><strong>Your tokens stay clean</strong>: All the extra stuff lives in a designated place</li>
<li><strong>Tools ignore what they don't understand</strong>: A token can pass through multiple tools and not lose data, even if those tools don't know about each others' extensions</li>
<li><strong>No waiting for spec updates</strong>: Teams can try new approaches immediately instead of proposing, debating, and waiting for standardisation</li>
</ol>
<h2 id="real-world-examples" tabindex="-1">Real-world examples</h2>
<h3 id="tool-integration" tabindex="-1">Tool integration</h3>
<p>If you're syncing tokens between Figma and your codebase, you might want to store Figma's internal IDs:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"primary-blue"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#0066CC"</span><span class="token punctuation">,</span>
    <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"com.figma.tokens"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"styleId"</span><span class="token operator">:</span> <span class="token string">"S:abc123def"</span><span class="token punctuation">,</span>
        <span class="token property">"lastSynced"</span><span class="token operator">:</span> <span class="token string">"2026-01-28T10:30:00Z"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="team-governance" tabindex="-1">Team governance</h3>
<p>Or maybe your design system has approval workflows and you need to track who owns what:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"heading-large"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"typography"</span><span class="token punctuation">,</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token comment">/* ... */</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"com.acme.governance"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"owner"</span><span class="token operator">:</span> <span class="token string">"design-system-team"</span><span class="token punctuation">,</span>
        <span class="token property">"approvedBy"</span><span class="token operator">:</span> <span class="token string">"jane.doe@acme.com"</span><span class="token punctuation">,</span>
        <span class="token property">"approvalDate"</span><span class="token operator">:</span> <span class="token string">"2026-01-15"</span><span class="token punctuation">,</span>
        <span class="token property">"usageGuidelines"</span><span class="token operator">:</span> <span class="token string">"https://docs.acme.com/tokens/heading-large"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="build-time-metadata" tabindex="-1">Build-time metadata</h3>
<p>Style Dictionary might need specific transforms for certain tokens:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"spacing-md"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"16px"</span><span class="token punctuation">,</span>
    <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"io.github.style-dictionary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"transforms"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"size/rem"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token property">"platforms"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"web"</span><span class="token punctuation">,</span> <span class="token string">"ios"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token property">"category"</span><span class="token operator">:</span> <span class="token string">"spacing"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="accessibility-data" tabindex="-1">Accessibility data</h3>
<p>You could even attach contrast ratios or WCAG conformance info. This is a good example of <em>computed or derived</em> metadata. The contrast ratio isn't inherent to the token itself, but depends on what you're comparing it against.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"text-body"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#333333"</span><span class="token punctuation">,</span>
    <span class="token property">"$extensions"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"org.w3.wcag"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"contrastRatio"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"onWhite"</span><span class="token operator">:</span> <span class="token number">12.6</span><span class="token punctuation">,</span>
          <span class="token property">"onPrimaryBg"</span><span class="token operator">:</span> <span class="token number">4.8</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"level"</span><span class="token operator">:</span> <span class="token string">"AAA"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>These examples focus on token-level extensions (the most common case), but <code>$extensions</code> also works at group and root levels. Use whatever scope makes sense for your metadata.</p>
</div>
<h2 id="real-world-support" tabindex="-1">Real-world support</h2>
<p>The DTCG spec reached a stable version (2025.10) in October 2025, and adoption seems to be happening fast, although unevenly.</p>
<p>Figma announced native support at their 2025 Schema conference. You can now export variables as spec-compliant JSON and import them back. However, Figma's not preserving <code>$extensions</code> (yet). If you import a token file with extensions, they will get removed when you export them.</p>
<p>Penpot did it differently. They were the first design tool to natively implement the specification (working with <a href="https://tokens.studio">Tokens Studio</a>), including <code>$extensions</code> support. You can import and export tokens with custom extensions, and Penpot preserves what it doesn't understand, exactly how the specification intends.</p>
<p>Build tools are where things get interesting. Style Dictionary, Tokens Studio, and Terrazzo all have solid <code>$extensions</code> support out of the box.</p>
<p>But here's the thing.</p>
<p>The spec says tools should preserve extensions they don't understand, and not all of them are there yet. If your workflow relies on <code>$extensions</code> for important metadata, you need to know which tools will keep that data and which won't.</p>
<h2 id="what-not-to-put-in-%24extensions" tabindex="-1">What not to put in <code>$extensions</code></h2>
<p>Just because you <em>can</em> put something in extensions doesn't mean you should. Here's what to avoid:</p>
<ul>
<li><strong>Data that changes a token's meaning</strong>: This belongs in the core spec properties, not extensions</li>
<li><strong>Secrets or sensitive information</strong>: Token files are often committed to version control, so don't store API keys, credentials, or anything that shouldn't be in a repo</li>
<li><strong>Massive amounts of data</strong>: Keep your token files parseable and version-control friendly</li>
</ul>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p><strong>Tools are free to ignore extensions entirely</strong>. A tool that only cares about the core spec can safely strip all <code>$extensions</code> and still have valid tokens. This is a feature, not a bug — it means your core token data is never held hostage by proprietary extensions.</p>
</div>
<h2 id="the-challenges" tabindex="-1">The challenges</h2>
<p>It's not perfect though. A few things to think about:</p>
<h3 id="file-bloat" tabindex="-1">File bloat</h3>
<p>Every extension you add makes your token files bigger. Larger files could mean slower parsing, bigger version control diffs, more overhead. You can manage this with smart tooling. Strip extensions for production builds, use compression, externalize large extension data, but it will require discipline and governance.</p>
<h3 id="fragmentation-risk" tabindex="-1">Fragmentation risk</h3>
<p>If teams all solve the same problems differently in their extensions, you would end up with incompatible ecosystems. One team uses <code>com.team1.metadata</code>, another uses <code>com.team2.metadata</code>, and suddenly migrating between them is painful.</p>
<p>The antidote? Document your extensions. Share them. When something proves valuable, perhaps propose it for standardisation. Your design system will work better when people aren't inventing in silos.</p>
<h3 id="discovery" tabindex="-1">Discovery</h3>
<p>There's no central registry of extensions (yet). If you want to know what extensions exist or how other teams handle something, you're basically having to reverse-engineer other peoples' token files. This will hopefully get better as the community matures.</p>
<h2 id="best-practices" tabindex="-1">Best practices</h2>
<p>If you're adding extensions to your tokens:</p>
<ul>
<li><strong>Document them</strong>: Include schemas, examples, and rationale</li>
<li><strong>Keep it optional</strong>: Never make extensions critical to understanding a token's actual value</li>
<li><strong>Version your extensions</strong>: If you change structure significantly, bump a version</li>
<li><strong>Think about preservation</strong>: If you're building a tool, always maintain extensions you don't understand</li>
<li><strong>Plan for obsolescence</strong>: Extensions can be a proving ground, not a forever home. When something is proven, consider proposing it for standardisation</li>
</ul>
<h2 id="the-bigger-picture" tabindex="-1">The bigger picture</h2>
<p><code>$extensions</code> represents a mature way of thinking about standards. It says: &quot;We're going to nail down what matters to everyone. For the rest, we'll create a clear, defined space where you can innovate without breaking things.&quot;</p>
<p>Too rigid, and the standard stifles innovation. Too loose, and you have chaos. I think this is a reasonable middle ground.</p>
<p>If you're working with design tokens, understanding how to use <code>$extensions</code> well should make your token files more flexible, more portable, and way more useful across different tools and workflows.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>I’ve been compiling my Sass wrong, for years</title>
      <link href="https://www.alwaystwisted.com/articles/ive-been-compiling-my-sass-wrong-for-years.html"/>
      <updated>2026-01-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/ive-been-compiling-my-sass-wrong-for-years.html</id>
      <content type="html">
        <![CDATA[
        <p>For years, I've been preprocessing Sass in my build pipeline without really thinking about how I was doing it. Every project would follow the same pattern: set up Sass, write a build script, and leave it alone. It worked. It was fast enough. I never questioned it.</p>
<p>That changed recently when I saw a deprecation warning in my build logs. It transpires, I've been using an API that's been obsolete for almost five years. And I didn't even know it.</p>
<h2 id="the-warning" tabindex="-1">The warning</h2>
<p>The warning was clear enough:</p>
<pre class="language-bash"><code class="language-bash">Deprecation Warning: The legacy JS API is deprecated and will be removed <span class="token keyword">in</span> Dart Sass <span class="token number">2.0</span>.0.</code></pre>
<p>I'd probably glanced over this warning a couple of times in recent weeks, but today it stopped me. I'm using <strong>Dart Sass</strong>. How was I possibly using a &quot;legacy&quot; API? I started digging and realised I've been clinging to <code>renderSync()</code> since my node-sass days.</p>
<h2 id="what-i-missed%2C-the-modern-api" tabindex="-1">What I missed, the modern API</h2>
<p>Back in late 2021, Dart Sass 1.45.0 introduced a fresh approach. Instead of <code>renderSync()</code>, the new API gave us:</p>
<ul>
<li><code>compile()</code> and <code>compileAsync()</code> for compiling files</li>
<li><code>compileString()</code> and <code>compileStringAsync()</code> for compiling strings directly</li>
</ul>
<p>These aren't just renamed methods. They're a proper redesign with better performance, cleaner syntax, proper Promise support instead of callbacks, and better TypeScript support.</p>
<h3 id="the-performance-bump" tabindex="-1">The performance bump</h3>
<p>The real surprise is the performance gain. When you use the modern API with <code>sass-embedded</code> (the faster Dart Sass implementation), you could be looking at <strong>5-10x faster</strong> compilation. That's not a marginal improvement. For projects with hundreds of imports, that's the difference between a build taking 30 seconds and 3 seconds.</p>
<p>Why? The old API was designed for the node-sass era, before modern Sass had its own compiler. The new API was built from the ground up for Dart Sass.</p>
<h2 id="migrating-the-code" tabindex="-1">Migrating the code</h2>
<p>Here's what the actual migration looks like. My old code using the legacy API:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> sass <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'sass'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Synchronous file compilation</span>
<span class="token keyword">const</span> result <span class="token operator">=</span> sass<span class="token punctuation">.</span><span class="token function">renderSync</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">file</span><span class="token operator">:</span> <span class="token string">'styles/main.scss'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">outputStyle</span><span class="token operator">:</span> <span class="token string">'compressed'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">sourceMap</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token literal-property property">outFile</span><span class="token operator">:</span> <span class="token string">'dist/main.css'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

fs<span class="token punctuation">.</span><span class="token function">writeFileSync</span><span class="token punctuation">(</span><span class="token string">'dist/main.css'</span><span class="token punctuation">,</span> result<span class="token punctuation">.</span>css<span class="token punctuation">)</span><span class="token punctuation">;</span>
fs<span class="token punctuation">.</span><span class="token function">writeFileSync</span><span class="token punctuation">(</span><span class="token string">'dist/main.css.map'</span><span class="token punctuation">,</span> result<span class="token punctuation">.</span>map<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The modern equivalent:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> sass <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'sass'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Synchronous file compilation</span>
<span class="token keyword">const</span> result <span class="token operator">=</span> sass<span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">'styles/main.scss'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token string">'compressed'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">sourceMap</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

fs<span class="token punctuation">.</span><span class="token function">writeFileSync</span><span class="token punctuation">(</span><span class="token string">'dist/main.css'</span><span class="token punctuation">,</span> result<span class="token punctuation">.</span>css<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>result<span class="token punctuation">.</span>sourceMap<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  fs<span class="token punctuation">.</span><span class="token function">writeFileSync</span><span class="token punctuation">(</span><span class="token string">'dist/main.css.map'</span><span class="token punctuation">,</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>result<span class="token punctuation">.</span>sourceMap<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>The key differences took me a moment to adjust to:</p>
<ol>
<li><strong>The file path is the first argument</strong> - Not buried in an options object. Much cleaner.</li>
<li><strong><code>outputStyle</code> is now <code>style</code></strong> - Just a property rename.</li>
<li><strong>No <code>outFile</code> needed</strong> - The modern API doesn't write files for you. You get back the CSS and source map, then handle the file writing yourself.</li>
<li><strong>CSS is already a string</strong> - No more calling <code>.toString()</code> on a Buffer.</li>
<li><strong>Source maps are objects</strong> - Not strings, so you stringify them when writing.</li>
</ol>
<h3 id="compiling-strings-instead-of-files" tabindex="-1">Compiling strings instead of files</h3>
<p>There are scenarios where you need to compile Sass without reading from a file. Build tools might construct Sass strings on-the-fly, or you could have a CMS that lets content editors define variables. Maybe you're generating a theme dynamically based on user input. In those cases, you're compiling strings directly:</p>
<p><strong>Old way:</strong></p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> result <span class="token operator">=</span> sass<span class="token punctuation">.</span><span class="token function">renderSync</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">data</span><span class="token operator">:</span> <span class="token string">'$primary: #333; body { color: $primary; }'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">outputStyle</span><span class="token operator">:</span> <span class="token string">'compressed'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><strong>New way:</strong></p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> result <span class="token operator">=</span> sass<span class="token punctuation">.</span><span class="token function">compileString</span><span class="token punctuation">(</span><span class="token string">'$primary: #333; body { color: $primary; }'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token string">'compressed'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="going-async" tabindex="-1">Going async</h3>
<p>One of the nice wins is async/await support. The old callback-based approach looked like this:</p>
<pre class="language-javascript"><code class="language-javascript">sass<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>
  <span class="token punctuation">{</span>
    <span class="token literal-property property">file</span><span class="token operator">:</span> <span class="token string">'styles/main.scss'</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> result</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>result<span class="token punctuation">.</span>css<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>With the modern API:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">compileSass</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token keyword">await</span> sass<span class="token punctuation">.</span><span class="token function">compileAsync</span><span class="token punctuation">(</span><span class="token string">'styles/main.scss'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>result<span class="token punctuation">.</span>css<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token function">compileSass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Much cleaner with async/await. If you're using this in a build tool or automation script, it's much more natural to work with.</p>
<h3 id="custom-functions-and-importers" tabindex="-1">Custom functions and importers</h3>
<p>Custom functions let you extend Sass with your own logic. You might need a function to calculate responsive sizes, generate colour variants, or perform calculations that Sass's built-in functions don't handle. Importers let you override how Sass finds and loads files (useful if you're loading Sass from a database, a package manager, or a custom file system). These are more advanced use cases, but if you're doing either, the API changed significantly.</p>
<p>The old way with custom functions:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> sass <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'sass'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> result <span class="token operator">=</span> sass<span class="token punctuation">.</span><span class="token function">renderSync</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">file</span><span class="token operator">:</span> <span class="token string">'styles/main.scss'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">functions</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token string-property property">'double($n)'</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">n<span class="token punctuation">,</span> done</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token function">done</span><span class="token punctuation">(</span>sass<span class="token punctuation">.</span>types<span class="token punctuation">.</span><span class="token function">Number</span><span class="token punctuation">(</span>n<span class="token punctuation">.</span><span class="token function">getValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">,</span> n<span class="token punctuation">.</span><span class="token function">getUnit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The modern approach:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> sass <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'sass'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> result <span class="token operator">=</span> sass<span class="token punctuation">.</span><span class="token function">compile</span><span class="token punctuation">(</span><span class="token string">'styles/main.scss'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">functions</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token string-property property">'double($n)'</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">args</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> n <span class="token operator">=</span> args<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">assertNumber</span><span class="token punctuation">(</span><span class="token string">'n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">sass<span class="token punctuation">.</span>SassNumber</span><span class="token punctuation">(</span>n<span class="token punctuation">.</span>value <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">,</span> n<span class="token punctuation">.</span>numeratorUnits<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The modern API uses a more robust system. It's less magical and more explicit, which honestly feels better.</p>
<h2 id="what-about-build-tools%3F" tabindex="-1">What about build tools?</h2>
<p>If you're using a build tool like webpack, Vite, or gulp, check whether they've updated their Sass integration. Most have, but support varies:</p>
<p><strong>sass-loader</strong> (for webpack) supports the modern API in v14+ if you set <code>api: 'modern-compiler'</code>. That option gives you the performance bump I mentioned earlier.</p>
<p><strong>Vite</strong> already uses the modern API by default, so if you're on a recent version, you're already getting the benefits.</p>
<p><strong>gulp-sass</strong> is still working on full migration support, though it's improving.</p>
<p>If you're configuring sass-loader, the setup is straightforward:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token punctuation">{</span>
  <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'sass-loader'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">api</span><span class="token operator">:</span> <span class="token string">'modern-compiler'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">implementation</span><span class="token operator">:</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'sass'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>That one option can make a noticeable difference in your build times if you've got a lot of Sass to process.</p>
<h2 id="should-you-update%3F" tabindex="-1">Should you update?</h2>
<p>Yes.</p>
<p>Here's why.</p>
<p><a href="https://github.com/sass/dart-sass/milestone/3">Dart Sass 2.0.0 is coming</a>, and the legacy API will be removed entirely. If you're still using <code>renderSync()</code> and <code>render()</code>, your build will break. There's no safety net, no deprecation option, no workaround.</p>
<p>Beyond that, the performance gains are real. If you're compiling Sass regularly as part of your workflow, cutting build times by 80-90% is worth the effort. The modern API is genuinely better to work with too.</p>
<p>If you do need time to migrate, you can suppress the warnings temporarily:</p>
<pre class="language-javascript"><code class="language-javascript">sass<span class="token punctuation">.</span><span class="token function">renderSync</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">file</span><span class="token operator">:</span> <span class="token string">'styles/main.scss'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">silenceDeprecations</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'legacy-js-api'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>But don't rely on that, you'll be forced to update eventually anyway.</p>
<h2 id="the-lesson" tabindex="-1">The lesson</h2>
<p>I've only just noticed the warnings in my build logs recently. I could have accidentally spent years skipping it thinking “It works&quot; was enough. Sometimes what works is just outdated, and you don't realise it until something forces you to look at it properly.</p>
<p>In this case, I didn’t know how much of a performance benefit I would be leaving on the table. I was using an API that had been superseded by something better, faster, and cleaner. All because I never upgraded a function call from (checks notes) 2015.</p>
<p>The <code>renderSync()</code> API served a purpose. It got Sass running in Node in the first place. But it's time to move on. The modern API isn't just a rename, it's a real improvement that makes your builds faster and your code cleaner.</p>
<p>So I've updated my build scripts. Compared to migrating from <code>@import</code> to <code>@use</code> and <code>@forward</code>, it didn't take long. The deprecation warning is gone and my builds are faster.</p>
<p>I probably should have done this when it came out five years ago, but at least I did it now.</p>
<p>If you're seeing that same deprecation warning in your logs, now is a good time to update yours too.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Introducing ReliCSS: A Tool for Front-End Archaeology</title>
      <link href="https://www.alwaystwisted.com/articles/introducing-relicss-a-tool-for-front-end-archaeology.html"/>
      <updated>2026-01-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/introducing-relicss-a-tool-for-front-end-archaeology.html</id>
      <content type="html">
        <![CDATA[
        <p>As a contracting front-end developer and Design Systems consultant, I don't always get to work on new things.</p>
<p>Sometimes I work within codebases. Sometimes alongside them. Sometimes these codebases are years and years old.</p>
<p>When you dive into these projects, you're not just reading code, you're excavating years of decisions, technological limitations, and creative workarounds from days gone by. Over the last decade, I've called this Front-End Archaeology.</p>
<h2 id="the-art-of-excavation" tabindex="-1">The Art of Excavation</h2>
<p>When I encounter a clearfix hack, I’m looking at a time when layout engines couldn't contain floated elements. When I see a &quot;doubled float margin bug&quot; fix, I’m witnessing “the scars” left by Internet Explorer 6. Every specific vendor prefix, every browser hack, and every strange <code>!important</code> rule tells a story of a developer fighting against the constraints of their time to ship a working product.</p>
<p>It’s easy to look at old code and judge it by modern standards, but Front-End Archaeology requires empathy and curiosity. It asks not just &quot;how do I delete this?&quot; but &quot;why was this necessary?&quot; and &quot;what can we learn from it?&quot;</p>
<p>Front-End Archaeology can take time. Identifying these artifacts manually requires deep historical knowledge of browser quirks that many modern developers (thankfully) never had to learn. That’s where tooling comes in.</p>
<h2 id="unearthing-history-with-relicss" tabindex="-1">Unearthing History with ReliCSS</h2>
<p>I've built a tool to help with this archaeological quest: <a href="https://www.alwaystwisted.com/relicss/">ReliCSS</a>.</p>
<p><img src="/images/articles/ReliCSS-interface-screenshot.jpg" alt="The ReliCSS interface showing the CSS scanner with code input area and results displaying severity levels for browser hacks" loading="lazy" decoding="async"></p>
<p>ReliCSS is an assistant during &quot;the dig&quot;. It's a dedicated scanner that analyses CSS to identify historical artifacts or &quot;browser hacks&quot; that can riddle older stylesheets.</p>
<p>Whether you're auditing a legacy codebase for a refactor or just curious about the history in your project's stylesheets, ReliCSS helps you spot “the ghosts in the machine”.</p>
<h3 id="how-it-works" tabindex="-1">How It Works</h3>
<p>Currently you can paste your CSS into the ReliCSS and it will parse it and highlight any browser hacks it finds.</p>
<p>For every “hack”, ReliCSS shows you the browser target, the context, and some suggestions to modernise it. ReliCSS assigns a <strong>Severity Level</strong> to help you prioritise what to refactor, and what you could or should remove:</p>
<ul>
<li><strong>High Severity:</strong> True “fossils”. Hacks for (now) unsupported browsers (IE6/7) or “dangerous” techniques. High-risk, obsolete, should be first targets for removal.</li>
<li><strong>Medium Severity:</strong> The middle ground. Hacks for older unsupported browsers (IE8-10). They work but they're fragile. Hacks to review to see if they're still relevant foryour actual users.</li>
<li><strong>Low Severity:</strong> Modern artifacts. Usually vendor prefixes (-webkit-, -moz-). Safe mostly, but better handled by automated tools like Autoprefixer. They're an opportunity to improve your build process.</li>
</ul>
<p>I’ve built ReliCSS so it runs entirely in the browser, with contractors and consultants in mind who could be working with sensitive client code. When you click &quot;Scan CSS,&quot; the analysis happens in the browser. No code gets sent to a server or anywhere else You can safely paste CSS without worrying about data leaks.</p>
<h2 id="the-roadmap%3A-future-excavation-tools" tabindex="-1">The Roadmap: Future Excavation Tools</h2>
<p>As mentioned, right now, ReliCSS works by pasting CSS directly. But I am looking at things that can beed added and improved. Here's what's coming:</p>
<ul>
<li><strong>Drag &amp; Drop Uploads:</strong> Drop a .css file directly into the tool for instant scanning.</li>
<li><strong>URL Fetching:</strong> Point ReliCSS at a live stylesheet and let it pull the artifacts.</li>
<li><strong>Command Line Interface (CLI):</strong> This is “the big one”. I'm working on bringing ReliCSS to your terminal. You'll be able to script the excavation process, integrate these checks into your build pipelines or local dev environments, catch hacks before they get buried again.</li>
</ul>
<h2 id="from-archaeology-to-modernisation" tabindex="-1">From Archaeology to Modernisation</h2>
<p>Front-end archaeology isn't just about admiring the ruins. It's about building on top of them safely. ReliCSS bridges the gap between the past and the present. It helps you confidently distinguish between load-bearing code and historical cruft.</p>
<p>By identifying which parts of your CSS exist only to support a 2006 browser, you can make informed decisions about what to keep, refactor, or delete. It can turn the daunting task of refactoring legacy CSS into an actual learning experience about web history.</p>
<p>If you find yourself staring at a stylesheet that looks like it survived the browser wars, give <a href="https://www.alwaystwisted.com/relicss/">ReliCSS</a> a try. You might learn something about where it came from and have an easier time getting it to where you want it to go.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 13) - Generating Utility Classes from Design Tokens using Style Dictionary</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-13.html"/>
      <updated>2025-11-21T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-13.html</id>
      <content type="html">
        <![CDATA[
        <p>This article shows a practical pattern for generating utility classes in CSS I’ve used in one form or another since 2016. Utility classes can give us a fast, consistent way to apply design system values in markup, without sprinkling hard‑coded styles across your project. As I discussed in my article on <a href="https://www.alwaystwisted.com/articles/creating-design-system-friendly-snowflakes-with-utility-classes">Creating Design System Friendly Snowflakes with Utility Classes</a>, utility classes can really help offer a middle ground between rigid components and completely custom CSS.</p>
<p>By generating utility classes directly from design tokens, we ensure that even any “one-off designs” stay consistent with our design system's values. If a design needs a specific spacing or colour that exists in our tokens, we can use a utility class rather than writing custom CSS with hard-coded values.</p>
<h2 id="defining-our-design-tokens" tabindex="-1">Defining Our Design Tokens</h2>
<p>To get things going, let’s define some design tokens for colour, spacing, and typography.</p>
<h3 id="colours" tabindex="-1">Colours</h3>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"red"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"500"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#f00"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ff4d4d"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"300"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ff9999"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"blue"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"500"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#007bff"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#66b3ff"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"300"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#99ccff"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"green"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"500"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#28a745"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#66d69f"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"300"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#99e6b3"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="spacing" tabindex="-1">Spacing</h3>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"100"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"0.25rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"200"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"0.5rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"300"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"0.75rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"500"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1.5rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"600"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"2rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"700"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"3rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="typography" tabindex="-1">Typography</h3>
<p>I’m going to split the examples for typography tokens into three separate files: <code>font-size.tokens</code>, <code>font-weight.tokens</code>, and <code>font-family.tokens</code>. This separation makes sense because font sizes, weights, and families often change at different rates (sizes might need frequent adjustments, while families rarely change), smaller, more focused files are easier to navigate and update rather than one large typography file, and we might decide to only generate utilities for sizes and weights but not families, for example.</p>
<h4 id="font-size" tabindex="-1">Font Size</h4>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"font"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"size"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"100"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"0.75rem"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"200"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"0.875rem"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"300"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1rem"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1.125rem"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"500"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1.25rem"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"600"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1.5rem"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"700"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1.75rem"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"800"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"2rem"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="font-weight" tabindex="-1">Font Weight</h4>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"font"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"weight"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"200"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"200"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"500"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"500"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"700"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"700"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="font-family" tabindex="-1">Font Family</h4>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"font"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"family"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Arial, sans-serif"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"code"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Consolas, monospace"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="utility-class-generation-script" tabindex="-1">Utility Class Generation Script</h2>
<p>When generating utility classes with Style Dictionary, how we structure our config or build script can make a real difference to how maintainable and scalable our setup becomes. I'm going to show two approaches. First, keeping everything in our ⁠build.js file, and then secondly, extracting the configuration into a separate ⁠utilities.js file.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom format for spacing utilities</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-spacing'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> utilities <span class="token operator">=</span> <span class="token punctuation">[</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'padding'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'padding'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'padding-top'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'padding-top'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'padding-right'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'padding-right'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'padding-bottom'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'padding-bottom'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'padding-left'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'padding-left'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'margin'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'margin'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'margin-top'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'margin-top'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'margin-right'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'margin-right'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'margin-bottom'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'margin-bottom'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'margin-left'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'margin-left'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">;</span>

    <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token string">'/* Spacing Utilities */\n\n'</span><span class="token punctuation">;</span>

    utilities<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">util</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      dictionary<span class="token punctuation">.</span>allTokens
        <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'spacing'</span><span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
          <span class="token keyword">const</span> className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>prefix<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>path<span class="token punctuation">[</span>token<span class="token punctuation">.</span>path<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
          output <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n  </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>property<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>$value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;\n}\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> output<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom format for colour utilities</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-color'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> utilities <span class="token operator">=</span> <span class="token punctuation">[</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'text'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'background'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'background-color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'border'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'border-color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">;</span>

    <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token string">'/* Colour Utilities */\n\n'</span><span class="token punctuation">;</span>

    utilities<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">util</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      dictionary<span class="token punctuation">.</span>allTokens
        <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'color'</span><span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
          <span class="token keyword">const</span> colorName <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token keyword">const</span> className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>prefix<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>colorName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
          output <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n  </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>property<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>$value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;\n}\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> output<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom format for font-size utilities</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-font-size'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token string">'/* Font Size Utilities */\n\n'</span><span class="token punctuation">;</span>

    dictionary<span class="token punctuation">.</span>allTokens
      <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'font'</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'size'</span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> size <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span>token<span class="token punctuation">.</span>path<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token keyword">const</span> className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">font-size--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>size<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        output <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n  font-size: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>$value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;\n}\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> output<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom format for font-weight utilities</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-font-weight'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token string">'/* Font Weight Utilities */\n\n'</span><span class="token punctuation">;</span>

    dictionary<span class="token punctuation">.</span>allTokens
      <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'font'</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'weight'</span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> weight <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span>token<span class="token punctuation">.</span>path<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token keyword">const</span> className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">font-weight--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>weight<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        output <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n  font-weight: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>$value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;\n}\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> output<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom format for font-family utilities</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-font-family'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token string">'/* Font Family Utilities */\n\n'</span><span class="token punctuation">;</span>

    dictionary<span class="token punctuation">.</span>allTokens
      <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'font'</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'family'</span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> family <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span>token<span class="token punctuation">.</span>path<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token keyword">const</span> className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">font-family--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>family<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        output <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n  font-family: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>$value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;\n}\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> output<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Build configuration</span>
<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'src/tokens/base/**/*.tokens'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">preprocessors</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'tokens-studio'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'utilities-spacing.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/utility-spacing'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'utilities-color.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/utility-color'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'utilities-font-size.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/utility-font-size'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'utilities-font-weight.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/utility-font-weight'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'utilities-font-family.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/utility-font-family'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">await</span> myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="understanding-the-custom-formats" tabindex="-1">Understanding the Custom Formats</h3>
<p>Let's break down how <code>StyleDictionary.registerFormat()</code> works using the colour utilities as an example:</p>
<pre class="language-javascript"><code class="language-javascript">StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-color'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// ... format logic</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><code>StyleDictionary.registerFormat()</code> tells Style Dictionary &quot;I want to create a new output format that we can use when generating files.&quot; The <code>name</code> property (<code>’css/utility-color'</code> in this case) is the unique identifier for our format. Later, when we configure the build, we reference this <code>name</code> to tell Style Dictionary which format to use for a specific file—in our case, we use <code>format: 'css/utility-color'</code> in the files array to connect this custom format to the <code>utilities-color.css</code> output file.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'utilities-color.css'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/utility-color'</span><span class="token punctuation">,</span> <span class="token comment">// References the name here</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span></code></pre>
<p>Here in the build configuration, we reference the format by its name (⁠<code>’css/utility-color'</code>) to tell Style Dictionary which custom format to use when generating the <code>⁠utilities-color.css</code> file.</p>
<h3 id="inside-the-format-function%3A" tabindex="-1">Inside the format function:</h3>
<pre class="language-javascript"><code class="language-javascript"><span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// Define what we want to generate</span>
  <span class="token keyword">const</span> utilities <span class="token operator">=</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'text'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'background'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'background-color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'border'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'border-color'</span> <span class="token punctuation">}</span>
  <span class="token punctuation">]</span><span class="token punctuation">;</span>

  <span class="token comment">// Start building the CSS output as a string</span>
  <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token string">'/* Colour Utilities */\n\n'</span><span class="token punctuation">;</span>

  <span class="token comment">// Loop through each utility type (text, background, border)</span>
  utilities<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">util</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token comment">// Access all tokens and filter to only colour tokens</span>
    dictionary<span class="token punctuation">.</span>allTokens
      <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">token</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'color'</span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">token</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
        <span class="token comment">// Build the class name from the token path, token.path might be ['color', 'red', '500']. slice(1) removes 'color', leaving ['red', '500']. join('-') creates 'red-500'</span>
        <span class="token keyword">const</span> colorName <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">const</span> className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>prefix<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>colorName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

        <span class="token comment">// Generate the CSS rule</span>
        output <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n  </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>property<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>$value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;\n}\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Return the complete CSS string</span>
  <span class="token keyword">return</span> output<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>There are a few key things to understand here. ⁠<code>dictionary.allTokens</code> is an array containing every token from our files after they've been processed. Each token has a <code>⁠path</code> property representing the structure of our token. For example, a token at ⁠<code>color.red.500</code> has the path ⁠[<code>’color', 'red', '500'</code>]. The <code>⁠token.$value</code> property contains the value (e.g., ⁠<code>#f00</code>). What’s returned becomes the content for the generated file(s).</p>
<p>When Style Dictionary runs, it loads all of the tokens found in <code>⁠src/tokens/base/**/*.tokens</code>, it looks for the file configuration that uses <code>⁠format: 'css/utility-color'</code>, calls the custom format function, and takes the returned information and generates ⁠<code>build/css/utilities-color.css</code>.</p>
<p>This will create a CSS file like:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Colour Utilities */</span>

<span class="token selector">.text-red-500</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #f00<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.text-red-400</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #ff4d4d<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.bg-blue-500</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> #007bff<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* ... and so on */</span></code></pre>
<h2 id="improving-the-build-script-with-a-separate-config-file" tabindex="-1">Improving the build script with a separate config file</h2>
<p>Even with only creating utility classes the build.js is starting to feeling crowded, so we’re going to ‘extract’ the configuration data into a separate file. This separates <em>what</em> utilities we want from <em>how</em> they're generated.</p>
<p>Create a <code>config/utilities.js</code> file</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">export</span> <span class="token keyword">const</span> utilityConfig <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">spacing</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'padding'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'padding'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'padding-top'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'padding-top'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'padding-right'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'padding-right'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'padding-bottom'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'padding-bottom'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'padding-left'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'padding-left'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'margin'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'margin'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'margin-top'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'margin-top'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'margin-right'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'margin-right'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'margin-bottom'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'margin-bottom'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'margin-left'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'margin-left'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">color</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'text'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'background'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'background-color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'border'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'border-color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">fontSize</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'font-size'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'font-size'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">fontWeight</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'font-weight'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'font-weight'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">fontFamily</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'font-family'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'font-family'</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>With this file now available it’s time to update the <code>build.js</code> to import it and use it:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> utilityConfig <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./config/utilities.js'</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom format for spacing utilities</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-spacing'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token string">'/* Spacing Utilities */\n\n'</span><span class="token punctuation">;</span>

    utilityConfig<span class="token punctuation">.</span>spacing<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">util</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      dictionary<span class="token punctuation">.</span>allTokens
        <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'spacing'</span><span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
          <span class="token keyword">const</span> className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>prefix<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>path<span class="token punctuation">[</span>token<span class="token punctuation">.</span>path<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
          output <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n  </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>property<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>$value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;\n}\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> output<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom format for colour utilities</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-color'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token string">'/* Colour Utilities */\n\n'</span><span class="token punctuation">;</span>

    utilityConfig<span class="token punctuation">.</span>color<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">util</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      dictionary<span class="token punctuation">.</span>allTokens
        <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'color'</span><span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
          <span class="token keyword">const</span> colorName <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'--'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token keyword">const</span> className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>prefix<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>colorName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
          output <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n  </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>property<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>$value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;\n}\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> output<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-font-size'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token string">'/* Font Size Utilities */\n\n'</span><span class="token punctuation">;</span>

    utilityConfig<span class="token punctuation">.</span>fontSize<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">util</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      dictionary<span class="token punctuation">.</span>allTokens
        <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'font'</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'size'</span><span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
          <span class="token keyword">const</span> size <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span>token<span class="token punctuation">.</span>path<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
          <span class="token keyword">const</span> className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>prefix<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>size<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
          output <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n  </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>property<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>$value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;\n}\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> output<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-font-weight'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token string">'/* Font Weight Utilities */\n\n'</span><span class="token punctuation">;</span>

    utilityConfig<span class="token punctuation">.</span>fontWeight<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">util</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      dictionary<span class="token punctuation">.</span>allTokens
        <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>
          <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'font'</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'weight'</span>
        <span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
          <span class="token keyword">const</span> weight <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span>token<span class="token punctuation">.</span>path<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
          <span class="token keyword">const</span> className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>prefix<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>weight<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
          output <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n  </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>property<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>$value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;\n}\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> output<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-font-family'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token string">'/* Font Family Utilities */\n\n'</span><span class="token punctuation">;</span>

    utilityConfig<span class="token punctuation">.</span>fontFamily<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">util</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      dictionary<span class="token punctuation">.</span>allTokens
        <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>
          <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'font'</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'family'</span>
        <span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
          <span class="token keyword">const</span> family <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span>token<span class="token punctuation">.</span>path<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
          <span class="token keyword">const</span> className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>prefix<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>family<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
          output <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n  </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>property<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>$value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;\n}\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> output<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Build configuration</span>
<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'src/tokens/base/**/*.tokens'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">preprocessors</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'tokens-studio'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'utilities-spacing.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/utility-spacing'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'utilities-color.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/utility-color'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'utilities-font-size.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/utility-font-size'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'utilities-font-weight.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/utility-font-weight'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'utilities-font-family.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/utility-font-family'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">await</span> myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="what%E2%80%99s-changed-here%3F" tabindex="-1">What’s changed here?</h3>
<p>As mentioned above, the difference between these two approaches is where the utility definitions are defined. In the first approach, they are defined directly inside each format function.</p>
<pre class="language-javascript"><code class="language-javascript">StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-color'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> utilities <span class="token operator">=</span> <span class="token punctuation">[</span>
      <span class="token comment">// Defined here, inside the function</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'text'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'background'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'background-color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'border'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'border-color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">;</span>

    utilities<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">util</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token comment">// ... generate CSS</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>By separating the configuration for the utilities we are importing them from the external file into the <code>build.js</code> script</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> utilityConfig <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./config/utilities.js'</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-color'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// No utilities array defined here</span>

    utilityConfig<span class="token punctuation">.</span>color<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">util</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token comment">// Using imported config instead</span>
      <span class="token comment">// ... generate CSS (same logic as before)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The format function itself does exactly the same work, looping through utilities and generating CSS. The only difference is the source of the utility definitions. Instead of hardcoding them in the build script, we're pulling them from <code>⁠utilityConfig.color</code>, which comes from our separate <code>config/utilities.js</code> configuration file.</p>
<p>This way when we want to add a new utility (say, <code>⁠.outline-red-500</code> for <code>⁠outline-color</code>), we edit ⁠<code>config/utilities.js</code> and add ⁠<code>{ prefix: 'outline', property: 'outline-color' }</code> to the ⁠colour array. The build script doesn't need to change at all and should automatically pick up the new definitions and generate the relevant utility classes.</p>
<h2 id="comparing-the-approaches" tabindex="-1">Comparing the Approaches</h2>
<p>Starting with everything in ⁠<code>build.js</code> can work well because everything is visible in one file and we can see exactly what's happening. There are no additional files to manage or import, making it perfect for getting started or for smaller projects. It's also easy to debug since all the logic is in one place.</p>
<p>However, this approach could fall short as the project grows. As we add more utility types, other formats (<code>.scss</code>, <code>.js</code> that are needed for the work the file can quickly grow, and the utility definitions could get mixed with the generation logic. If we wanted to reuse this setup in another project, we might need to copy the entire file, and making changes to utility definitions requires editing the build script itself.</p>
<p>Moving to a ‘separated configuration’ can improve things considerably. The configuration for the utility classes is separated from logic, making it easier to see what we’re going to be generating. Our ⁠build.js should become cleaner and more focused on only the generation process. The configuration file could be shared across projects and non-developers can more easily make changes to utility definitions without touching the build logic.</p>
<p>However, there are some things to consider with this approach. We will now have (at least) two files to maintain instead of one, the build script still needs to register each format individually, and we are still repeating similar logic for each utility type. But for most projects, these trade-offs are worth the improved organisation and maintainability.</p>
<h3 id="generated-output" tabindex="-1">Generated Output</h3>
<p>Regardless of which configuration approach we choose, the output remains the same. Here's what gets generated:</p>
<h4 id="utilities-spacing.css" tabindex="-1">utilities-spacing.css</h4>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Spacing Utilities */</span>

<span class="token selector">.padding--100</span> <span class="token punctuation">{</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> 0.25rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.padding--200</span> <span class="token punctuation">{</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.padding-top--100</span> <span class="token punctuation">{</span>
  <span class="token property">padding-top</span><span class="token punctuation">:</span> 0.25rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.margin-top--400</span> <span class="token punctuation">{</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* ... more utilities */</span></code></pre>
<h4 id="utilities-color.css" tabindex="-1">utilities-color.css</h4>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Colour Utilities */</span>

<span class="token selector">.text-red--500</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #f00<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.bg-blue--400</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> #66b3ff<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.border-green--300</span> <span class="token punctuation">{</span>
  <span class="token property">border-color</span><span class="token punctuation">:</span> #99e6b3<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* ... more utilities */</span></code></pre>
<h4 id="utilities-font-size.css" tabindex="-1">utilities-font-size.css</h4>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Font Size Utilities */</span>

<span class="token selector">.font-size--100</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 0.75rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.font-size--300</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.font-size--600</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* ... more utilities */</span></code></pre>
<h2 id="generating-semantic-utility-classes" tabindex="-1">Generating Semantic Utility Classes</h2>
<p>While the utilities we've generated so far use the raw token names (like <code>.text-500</code> or <code>.background-blue-400</code>), it could be better if we generated more semantic utility classes that better communicate intent of our design decisions.</p>
<p>For example, if we have semantic colour tokens file like:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"semantic"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.blue.500}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"danger"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.red.500}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"success"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.green.500}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>We could create a separate format that generates semantic utilities:</p>
<pre class="language-javascript"><code class="language-javascript">StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'css/utility-semantic-color'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> utilities <span class="token operator">=</span> <span class="token punctuation">[</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'text'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'background'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'background-color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">prefix</span><span class="token operator">:</span> <span class="token string">'border'</span><span class="token punctuation">,</span> <span class="token literal-property property">property</span><span class="token operator">:</span> <span class="token string">'border-color'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">;</span>

    <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token string">'/* Semantic Colour Utilities */\n\n'</span><span class="token punctuation">;</span>

    utilities<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">util</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      dictionary<span class="token punctuation">.</span>allTokens
        <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>
          <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'color'</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'semantic'</span>
        <span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
          <span class="token keyword">const</span> semanticName <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">[</span>token<span class="token punctuation">.</span>path<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
          <span class="token keyword">const</span> className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>prefix<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>semanticName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
          output <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>className<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n  </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>util<span class="token punctuation">.</span>property<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>$value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;\n}\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> output<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This would generate utilities like:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.text--primary</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #007bff<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.background--danger</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> #f00<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.border--success</span> <span class="token punctuation">{</span>
  <span class="token property">border-color</span><span class="token punctuation">:</span> #28a745<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This approach can give us both the flexibility of low-level utilities (<code>.text-500</code>) and the clarity of semantic utilities (<code>.text-primary</code>).</p>
<p>Generating utility classes from our design tokens can help ‘bridge the gap’ between our design system and the potential fast-paced, real-world needs of building interfaces.</p>
<p>By automating this process with Style Dictionary, we can ensure that utility classes should stay in sync with our tokens. When we update a token value, the utility classes can be automatically updated. Teams are now constrained to use system values even for one-off designs, keeping everything aligned and being able to create things that are ‘of the Design System’ but not necessarily something that will ever become something that is ‘from the Design System’.</p>
<p>You can find the code for this article in <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/13-generating-utility-classes">this branch of the github repo</a> for this series.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Few Useful Web Development Bookmarklets</title>
      <link href="https://www.alwaystwisted.com/articles/a-few-web-developer-bookmarklets.html"/>
      <updated>2025-10-23T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-few-web-developer-bookmarklets.html</id>
      <content type="html">
        <![CDATA[
        <p>I started creating a few bookmarklets (small JavaScript snippets saved as browser bookmarks) when working with a client which involved some 'front-end archeology' looking at a codebase that was 15 years mature and has been worked on since. These tools helped me quickly understand the structure, dependencies, and technical debt without having to dive deep into the codebase first.</p>
<p>The bookmarklets I've created focus on some common web development inspection tasks that aren't always easy to accomplish with standard browser developer tools:</p>
<ol>
<li>Toggling between JavaScript and non-JavaScript states.</li>
<li>Finding inline CSS in the document.</li>
<li>Identifying elements with inline styles.</li>
<li>Detecting third-party resources.</li>
<li>Highlighting design system component usage.</li>
</ol>
<p>Each of these addresses specific challenges I faced when trying to understand and document legacy front-end code. They've proven particularly valuable when auditing sites with multiple developers' contributions over many years, revealing patterns and issues that could remain hidden.</p>
<p>These bookmarklets don't attempt to replace comprehensive developer tools, but rather complement them by providing quick insights for specific front-end investigation.</p>
<h2 id="js%2Fno-js-toggle" tabindex="-1">JS/No-JS Toggle</h2>
<p>This bookmarklet toggles between <a href="https://www.google.com/search?client=safari&amp;rls=en&amp;q=paul+irish+no-js&amp;ie=UTF-8&amp;oe=UTF-8">the js and no-js classes on the HTML element</a>. It's useful for testing how your site behaves with and without JavaScript enabled.</p>
<a href="javascript:(function(){var htmlElement=document.documentElement;if(htmlElement.classList.contains('js')){htmlElement.classList.remove('js');htmlElement.classList.add('no-js');}else{htmlElement.classList.remove('no-js');htmlElement.classList.add('js');}})();">No No No No JS</a><h2 id="inline-css-inspector" tabindex="-1">Inline CSS Inspector</h2>
<p>This bookmarklet displays all inline CSS styles in the document head and style blocks in the page, along with line numbers and formatting.</p>
<a href="javascript:(function(){var d=document;var styles=Array.from(d.head.getElementsByTagName('style')).filter(s=>!s.hasAttribute('data-styled')&&!s.hasAttribute('data-emotion'));var c=d.createElement('div');c.style.cssText='position:fixed!important;top:0!important;left:0!important;right:0!important;z-index:9999!important;background:#fff!important;color:#000!important;padding:15px!important;border-bottom:2px solid #000!important;max-height:80vh!important;overflow:auto!important;font:14px Arial!important;box-shadow:0 2px 10px rgba(0,0,0,0.3)!important;';var html='<h3 style=\'margin:0 0 15px!important;font:bold 18px Arial!important;color:#000!important;\'>Inline CSS in HEAD</h3>';if(styles.length===0){html+='<div style=\'padding:10px!important;background:#f5f5f5!important;color:#000!important;border-left:3px solid #f33!important;\'>No inline CSS found in the HEAD element.</div>';}else{html+='<div style=\'margin-bottom:10px!important;color:#000!important;\'>Found <strong>'+styles.length+'</strong> style blocks:</div>';styles.forEach(function(style,index){var cssText=style.textContent.trim().replace(/}/g,'}\n').replace(/{/g,' {\n  ').replace(/;/g,';\n  ');html+='<div style=\'margin:10px 0!important;padding:10px!important;background:#f5f5f5!important;border:1px solid #ddd!important;border-radius:3px!important;\'><div style=\'color:#06a!important;font:bold 14px monospace!important;margin-bottom:5px!important;\'>Style Block #'+(index+1)+' <span style=\'color:#777!important;font-weight:normal!important;font-size:12px!important;\'>('+cssText.length+' characters)</span></div><pre style=\'margin:0!important;padding:8px!important;background:#fff!important;color:#333!important;font:13px monospace!important;overflow:auto!important;white-space:pre-wrap!important;border:1px solid #eee!important;max-height:300px!important;\'>'+cssText.replace(/</g,'&lt;').replace(/>/g,'&gt;')+'</pre></div>';});}html+='<div id=\'inline-css-close-btn\' style=\'position:absolute!important;top:10px!important;right:10px!important;background:#f33!important;color:#fff!important;border:none!important;padding:5px 10px!important;border-radius:3px!important;cursor:pointer!important;\'>Close</div>';c.innerHTML=html;d.body.appendChild(c);document.getElementById('inline-css-close-btn').addEventListener('click',function(){c.remove();});})();">Inline CSS Inspector</a><p><img src="/images/bookmarklets/css.png" alt="a screenshot showing results of this bookmarklet" loading="lazy" decoding="async"></p>
<h2 id="inline-element-styles-inspector" tabindex="-1">Inline Element Styles Inspector</h2>
<p>This bookmarklet scans the entire page for HTML elements that have inline ⁠style attributes and displays a comprehensive report.</p>
<a href="javascript:(function(){var d=document;var elements=Array.from(d.querySelectorAll('*')).filter(function(el){return el.hasAttribute('style')&&el.getAttribute('style').trim()!=='';});var c=d.createElement('div');c.style.cssText='position:fixed!important;top:0!important;left:0!important;right:0!important;z-index:9999!important;background:#fff!important;color:#000!important;padding:15px!important;border-bottom:2px solid #000!important;max-height:80vh!important;overflow:auto!important;font:14px Arial!important;box-shadow:0 2px 10px rgba(0,0,0,0.3)!important;';var h='<h3 style=\'margin:0 0 15px!important;font:bold 18px Arial!important;color:#000!important;\'>Inline Style Inspector</h3>';if(elements.length===0){h+='<div style=\'padding:10px!important;background:#f5f5f5!important;color:#000!important;border-left:3px solid #f33!important;\'>No elements with inline styles found on this page.</div>';}else{h+='<div style=\'margin-bottom:10px!important;color:#000!important;\'>Found <strong>'+elements.length+'</strong> elements with inline styles:</div>';for(var i=0;i<elements.length;i++){var el=elements[i];var tag=el.tagName.toLowerCase();var identifier='';if(el.id)identifier+=' id=\''+el.id+'\'';if(el.className)identifier+=' class=\''+el.className+'\'';var domPath=[];var currentEl=el;var depth=0;while(currentEl&&currentEl!==document.body&&domPath.length<3){var name=currentEl.tagName.toLowerCase();if(currentEl.id)name+='#'+currentEl.id;domPath.unshift(name);currentEl=currentEl.parentElement;depth++;}h+='<div style=\'margin:10px 0!important;padding:10px!important;background:#f5f5f5!important;border:1px solid #ddd!important;border-radius:3px!important;\'><div style=\'color:#06a!important;font:bold 14px monospace!important;margin-bottom:5px!important;\'>&lt;'+tag+identifier+'&gt; <span style=\'color:#777!important;font-weight:normal!important;font-size:12px!important;\'>(#'+(i+1)+', Depth: '+depth+')</span></div><div style=\'color:#666!important;font:12px monospace!important;margin-bottom:5px!important;\'>'+domPath.join(' > ')+'</div><pre style=\'margin:0!important;padding:8px!important;background:#fff!important;color:#333!important;font:13px monospace!important;overflow:auto!important;white-space:pre-wrap!important;border:1px solid #eee!important;\'>'+el.getAttribute('style').replace(/</g,'&lt;').replace(/>/g,'&gt;')+'</pre></div>';}}h+='<div id=\'inline-styles-close-btn\' style=\'position:absolute!important;top:10px!important;right:10px!important;background:#f33!important;color:#fff!important;border:none!important;padding:5px 10px!important;border-radius:3px!important;cursor:pointer!important;\'>Close</div>';c.innerHTML=h;d.body.appendChild(c);document.getElementById('inline-styles-close-btn').addEventListener('click',function(){c.remove();});})();">Inline Style Inspector</a><p><img src="/images/bookmarklets/inline-styles.png" alt="a screenshot showing results of this bookmarklet" loading="lazy" decoding="async"></p>
<h4 id="why-this-bookmarklet-is-useful" tabindex="-1">Why This Bookmarklet is Useful</h4>
<p>This inline styles inspector aids in code audits to identify styles for external stylesheets, debugging layout issues, performance optimization through consolidating redundant styles, and checking for styles that might override accessibility features.</p>
<h2 id="third-party-resource-detector" tabindex="-1">Third-Party Resource Detector</h2>
<p>This bookmarklet identifies and lists all external CSS and JavaScript files loaded from domains other than the current one.</p>
<a href="javascript:(function(){var d=document;var currentHost=window.location.hostname;function extractDomain(url){try{return new URL(url).hostname;}catch(e){return url;}}function getBaseDomain(domain){var parts=domain.split('.');if(parts.length<=2)return domain;var baseDomain=parts.slice(parts.length-2).join('.');return baseSiteDomain;}var baseSiteDomain=getBaseDomain(currentHost);var externalResources=[];var links=d.getElementsByTagName('link');var scripts=d.getElementsByTagName('script');for(var i=0;i<links.length;i++){if(links[i].href){var linkDomain=extractDomain(links[i].href);if(getBaseDomain(linkDomain)!==baseSiteDomain){var type=links[i].rel==='stylesheet'?'CSS':(links[i].rel||'Link');externalResources.push({type:type,url:links[i].href});}}}for(var j=0;j<scripts.length;j++){if(scripts[j].src){var scriptDomain=extractDomain(scripts[j].src);if(getBaseDomain(scriptDomain)!==baseSiteDomain){externalResources.push({type:'JS',url:scripts[j].src});}}}var c=d.createElement('div');c.style.cssText='position:fixed!important;top:0!important;left:0!important;right:0!important;z-index:9999!important;background:#fff!important;color:#000!important;padding:15px!important;border-bottom:2px solid #000!important;max-height:80vh!important;overflow:auto!important;font:14px Arial!important;box-shadow:0 2px 10px rgba(0,0,0,0.3)!important;';var html='<h3 style=\'margin:0 0 15px!important;font:bold 18px Arial!important;color:#000!important;\'>External Resources</h3>';if(externalResources.length===0){html+='<div style=\'padding:10px!important;background:#f5f5f5!important;color:#000!important;border-left:3px solid #f33!important;\'>No external resources found.</div>';}else{html+='<div style=\'margin-bottom:10px!important;color:#000!important;\'>Found <strong>'+externalResources.length+'</strong> truly external resources:</div>';externalResources.forEach(function(resource,index){var color=resource.type==='CSS'?'#06a':(resource.type==='JS'?'#850':'#444');html+='<div style=\'margin:10px 0!important;padding:10px!important;background:#f5f5f5!important;border:1px solid #ddd!important;border-radius:3px!important;\'><div style=\'color:'+color+'!important;font:bold 14px monospace!important;margin-bottom:5px!important;\'>'+resource.type+' #'+(index+1)+'</div><pre style=\'margin:0!important;padding:8px!important;background:#fff!important;color:#333!important;font:13px monospace!important;overflow:auto!important;white-space:pre-wrap!important;border:1px solid #eee!important;word-break:break-all!important;\'>'+resource.url+'</pre></div>';});}html+='<div id=\'external-resources-close-btn\' style=\'position:absolute!important;top:10px!important;right:10px!important;background:#f33!important;color:#fff!important;border:none!important;padding:5px 10px!important;border-radius:3px!important;cursor:pointer!important;\'>Close</div>';c.innerHTML=html;d.body.appendChild(c);document.getElementById('external-resources-close-btn').addEventListener('click',function(){c.remove();});})();">External Resources Detector</a><p><img src="/images/bookmarklets/3rd-party.png" alt="a screenshot showing results of this bookmarklet" loading="lazy" decoding="async"></p>
<h3 id="why-this-bookmarklet-is-useful-1" tabindex="-1">Why This Bookmarklet is Useful</h3>
<p>This external resource detector supports security auditing of third-party scripts, performance optimization, GDPR/privacy compliance checks, dependency management, Content Security Policy development, and assessment of offline capabilities by identifying external resources.</p>
<h2 id="component-checker" tabindex="-1">Component Checker</h2>
<p>This bookmarklet helps identify which elements use your design system classes. Elements with your design system prefix are highlighted in green, while all others are outlined in red.</p>
<a href="javascript:(function(){const prefix=prompt('Enter CSS class prefix:','vf-');if(prefix===null||prefix===''){return;}const elementsWithPrefix=document.querySelectorAll('*[class*=\''+prefix+'\']');const allElements=document.querySelectorAll('*');elementsWithPrefix.forEach(el=>{el.style.outline='2px solid green';el.style.position='relative';});allElements.forEach(el=>{if(![...el.classList].some(cls=>cls.startsWith(prefix))){el.style.outline='4px solid red';el.style.position='relative';}});})();">Component Checker</a><p><img src="/images/bookmarklets/component-checker.jpeg" alt="a screenshot showing results of this bookmarklet" loading="lazy" decoding="async"></p>
<h3 id="why-this-bookmarklet-is-useful-2" tabindex="-1">Why This Bookmarklet is Useful</h3>
<p>This component checker assists with design system compliance verification, legacy code detection, visual auditing of component adoption, refactoring planning, quality assurance of developer practices, and creating visual documentation of component usage patterns.</p>
<h3 id="customizing-the-component-checker" tabindex="-1">Customizing the Component Checker</h3>
<p>To adapt this bookmarklet for your own design system, simply modify the namespace value at the beginning of the code. Replace <code>vf-</code> with your own design system's class prefix.</p>
<h2 id="bonus---ass-morphism" tabindex="-1">Bonus - Ass Morphism</h2>
<p>A little fun bookmarklet that makes a dig at the new Liquid Glass or Glassmorphism design and will simply change where it used on a page with a little humour.</p>
<a href="javascript:(function() { document.body.innerHTML = document.body.innerHTML.replace(/glassmorphism/gi, 'assmorphism').replace(/liquid glass/gi, 'liquid ass'); })();">Ass Morphism</a>
      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Styling The gap with CSS</title>
      <link href="https://www.alwaystwisted.com/articles/styling-the-gap-with-css.html"/>
      <updated>2025-10-22T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/styling-the-gap-with-css.html</id>
      <content type="html">
        <![CDATA[
        <p>Back in 2017, while working at Monotype on their Design System, I was tasked with coding a new design for a set of logos. This design featured either a vertical line separator at larger viewports or a horizontal one at smaller screens, with the logos stacking as needed. Eager to implement the latest technology,
I opted for CSS Grid. However, the challenge was that, at the time, there was no straightforward way to add a graphical rule to the component without resorting to pseudo-elements and &quot;magic numbers&quot; to achieve a 1px wide line evenly spaced in the grid's margin.</p>
<p>Fast forward to 2025, and we’re on the brink of using new CSS features to create those horizontal or vertical rules (but with bells on).</p>
<p>In June, Patrick and Sam from Microsoft updated us on the Chrome blog about a ~<a href="https://blogs.windows.com/msedgedev/2025/03/19/minding-the-gaps-a-new-way-to-draw-separators-in-css/">previous announcement</a>~ regarding the ability to add ~<a href="https://developer.chrome.com/blog/gap-decorations#the_solution_css_gap_decorations">decorations to the gaps in our flex and grid layouts</a>~. Excited by this news, I spent a couple of hours tinkering in Chrome (Canary) to explore the new rules and their potential use cases. And here we are!</p>
<h2 id="css-gap-decorations" tabindex="-1">CSS Gap Decorations</h2>
<p>As I mentioned, before now (browser support not withstanding) we had to be intuitive if we came across a design that needed vertical or horizontal lines (or both) as part of a layout.
We could opt for using pseudo elements (⁠<code>::before</code>or <code>⁠::after</code>) or we could add additonal DOM elements but these could hit upon other issues. The workarounds could be unitiuitive, we could be adding more CSS that could break if layouts change, additional columns or rows are added. Adding additional DOM elements could work but we could hit upon accessibility issues.
This new specification clears these potential issues up rather neartly as they have no impact on the layouts they’re being applied to as they’re purely visual, they allow for pattern creation as they make use of ⁠<code>repeat()</code> and we don’t need extra markup, we can apply this CSS to what we have already.</p>
<h2 id="new-specification%2C-new-rules%2C-new-properties" tabindex="-1">New Specification, New Rules, New Properties</h2>
<p>The new gap decoration specification introduces familiar syntax, similar to how we write border properties in CSS. It brings two main sets of properties: one for column rules and one for row rules, each with their own width, style, and colour properties.</p>
<h3 id="individual-properties" tabindex="-1">Individual Properties</h3>
<p>For complete control, you can use individual properties:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Column decorations */</span>
<span class="token property">column-rule-width</span><span class="token punctuation">:</span> 2px<span class="token punctuation">;</span>
<span class="token property">column-rule-style</span><span class="token punctuation">:</span> solid<span class="token punctuation">;</span>
<span class="token property">column-rule-color</span><span class="token punctuation">:</span> #bada55<span class="token punctuation">;</span>

<span class="token comment">/* Row decorations */</span>
<span class="token property">row-rule-width</span><span class="token punctuation">:</span> 1px<span class="token punctuation">;</span>
<span class="token property">row-rule-style</span><span class="token punctuation">:</span> solid<span class="token punctuation">;</span>
<span class="token property">row-rule-color</span><span class="token punctuation">:</span> #c0ffee<span class="token punctuation">;</span></code></pre>
<h3 id="shorthand-syntax" tabindex="-1">Shorthand Syntax</h3>
<p>Just like with borders, you can combine these properties using shorthand:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Combined column properties */</span>
<span class="token property">column-rule</span><span class="token punctuation">:</span> 2px solid #bada55<span class="token punctuation">;</span>

<span class="token comment">/* Combined row properties */</span>
<span class="token property">row-rule</span><span class="token punctuation">:</span> 1px solid #c0ffee<span class="token punctuation">;</span></code></pre>
<h3 id="universal-rule" tabindex="-1">Universal Rule</h3>
<p>If you want the same decoration style for both rows and columns, there's a new universal shorthand:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Applied to both row and column gaps */</span>
<span class="token property">rule</span><span class="token punctuation">:</span> 2px solid #bada55<span class="token punctuation">;</span></code></pre>
<p>This new specification brings consistency to how we style gaps in our layouts, whether they're grid, flexbox, or multi-column. The syntax should hopefully feel familiar to anyone who's worked with borders, making it intuitive to implement while offering powerful new styling capabilities.</p>
<h3 id="specialised-properties" tabindex="-1">Specialised Properties</h3>
<p>The specification introduces some powerful properties that give us fine-grained control over how our gap decorations appear and interact. Let’s take a look at these in detail:</p>
<h4 id="rule-break" tabindex="-1">Rule Break</h4>
<p>The <code>rule-break</code> property controls how our gap decorations behave when they meet at intersections or spannign items:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Column decorations */</span>
<span class="token property">column-rule-break</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span> <span class="token comment">/* Lines continue through intersections */</span>
<span class="token property">column-rule-break</span><span class="token punctuation">:</span> intersection<span class="token punctuation">;</span> <span class="token comment">/* Lines stop at intersections */</span>
<span class="token property">column-rule-break</span><span class="token punctuation">:</span> spanning-item<span class="token punctuation">;</span> <span class="token comment">/* Lines break at spanning items */</span>

<span class="token comment">/* Row decorations */</span>
<span class="token property">row-rule-break</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
<span class="token property">row-rule-break</span><span class="token punctuation">:</span> intersection<span class="token punctuation">;</span>
<span class="token property">row-rule-break</span><span class="token punctuation">:</span> spanning-item<span class="token punctuation">;</span>

<span class="token comment">/* Shorthand for both */</span>
<span class="token property">rule-break</span><span class="token punctuation">:</span> intersection<span class="token punctuation">;</span></code></pre>
<p>This property is particularly useful when you need precise control over how your decorations interact with the layout. For example, in a calendar interface, you might want vertical lines to break at day headers that span multiple columns.</p>
<h4 id="rule-outset" tabindex="-1">Rule Outset</h4>
<p>The <code>⁠rule-outset</code> properties give us precise control over where decorations start and end relative to intersections:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Controls how far decorations extend from their central position */</span>
<span class="token property">column-rule-outset</span><span class="token punctuation">:</span> 50%<span class="token punctuation">;</span> <span class="token comment">/* Default - meets in the middle */</span>
<span class="token property">column-rule-outset</span><span class="token punctuation">:</span> 0px<span class="token punctuation">;</span> <span class="token comment">/* Aligns with edges */</span>
<span class="token property">column-rule-outset</span><span class="token punctuation">:</span> 5px<span class="token punctuation">;</span> <span class="token comment">/* Extends beyond edges */</span>
<span class="token property">column-rule-outset</span><span class="token punctuation">:</span> -5px<span class="token punctuation">;</span> <span class="token comment">/* Pulls back from edges */</span>

<span class="token comment">/* Same options for rows */</span>
<span class="token property">row-rule-outset</span><span class="token punctuation">:</span> 50%<span class="token punctuation">;</span>

<span class="token comment">/* Shorthand for both */</span>
<span class="token property">rule-outset</span><span class="token punctuation">:</span> 5px<span class="token punctuation">;</span></code></pre>
<p>The percentage values are relative to the gap width, which means they'll scale proportionally as your layout changes. This is particularly useful for responsive designs where gap sizes might vary.</p>
<h4 id="paint-order" tabindex="-1">Paint Order</h4>
<p>Finally, ⁠<code>rule-paint-order</code> lets us control which decorations appear on top when row and column rules intersect:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Row decorations appear on top of column decorations */</span>
<span class="token property">rule-paint-order</span><span class="token punctuation">:</span> row-over-column<span class="token punctuation">;</span>

<span class="token comment">/* Column decorations appear on top of row decorations */</span>
<span class="token property">rule-paint-order</span><span class="token punctuation">:</span> column-over-row<span class="token punctuation">;</span></code></pre>
<p>This property becomes especially important when working with different rule widths or styles. For example, if you're creating a notebook-style layout with thin vertical lines and thicker horizontal lines, you might want to ensure the horizontal lines appear on top for a more authentic look:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.notebook</span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span>
  <span class="token property">gap</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span>

  <span class="token property">column-rule</span><span class="token punctuation">:</span> 1px solid #ddd<span class="token punctuation">;</span>
  <span class="token property">row-rule</span><span class="token punctuation">:</span> 2px solid #000<span class="token punctuation">;</span>
  <span class="token property">rule-paint-order</span><span class="token punctuation">:</span> row-over-column<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="pattern-creation-with-%E2%81%A0repeat()" tabindex="-1">Pattern Creation with ⁠<code>repeat()</code></h3>
<p>Just like CSS Grid's ⁠<code>repeat() </code>function, gap decorations can use similar syntax to create patterns. This gives us powerful ways to style our gaps without writing repetitive CSS:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* Simple repetition of the same style */</span>
<span class="token property">row-rule</span><span class="token punctuation">:</span> <span class="token function">repeat</span><span class="token punctuation">(</span>solid<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Every row gap has a solid line */</span>

<span class="token comment">/* Alternating styles */</span>
<span class="token property">column-rule-style</span><span class="token punctuation">:</span> <span class="token function">repeat</span><span class="token punctuation">(</span>
  solid dotted
<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Alternates between solid and dotted lines */</span>

<span class="token comment">/* Complex patterns */</span>
<span class="token property">row-rule</span><span class="token punctuation">:</span> <span class="token function">repeat</span><span class="token punctuation">(</span>2<span class="token punctuation">,</span> 1px solid black<span class="token punctuation">)</span> 3px solid red<span class="token punctuation">;</span> <span class="token comment">/* Two thin black lines, then one thick red line */</span>

<span class="token comment">/* Multiple properties can use repeat */</span>
<span class="token property">column-rule-width</span><span class="token punctuation">:</span> <span class="token function">repeat</span><span class="token punctuation">(</span>1px 2px<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Alternating thin and thick lines */</span>
<span class="token property">column-rule-color</span><span class="token punctuation">:</span> <span class="token function">repeat</span><span class="token punctuation">(</span>#bada55 #c0ffee<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Alternating colours */</span></code></pre>
<p>These properties give us incredible flexibility... want your decorations to meet perfectly in the middle? Use the default 50%. Need them to stop right at the edges? Set it to 0. Want them to extend a bit further or pull back? Use positive or negative values accordingly.</p>
<h2 id="in-practice" tabindex="-1">In Practice</h2>
<p>Let’s go back to that brand logo component I needed to create in 2017. There were 5 logos that needed to go from being stacked on a narrow viewport to evenly place when the viewport was large enough.
The HTML would look something like this:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>logo-a.svg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>a logo of brand A<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>logo-b.svg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>a logo of brand B<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>logo-c.svg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>a logo of brand C<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>logo-d.svg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>a logo of brand D<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>logo-e.svg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>a logo of brand E<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">></span></span></code></pre>
<p>The CSS to make sure that the gap decorations are displayed as needed looks like this:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">ul</span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span>
  <span class="token property">gap</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">justify-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>

  <span class="token property">row-rule-width</span><span class="token punctuation">:</span> 1px<span class="token punctuation">;</span>
  <span class="token property">row-rule-style</span><span class="token punctuation">:</span> solid<span class="token punctuation">;</span>
  <span class="token property">row-rule-color</span><span class="token punctuation">:</span> black<span class="token punctuation">;</span>

  <span class="token property">column-rule-width</span><span class="token punctuation">:</span> 1px<span class="token punctuation">;</span>
  <span class="token property">column-rule-style</span><span class="token punctuation">:</span> solid<span class="token punctuation">;</span>
  <span class="token property">column-rule-color</span><span class="token punctuation">:</span> black<span class="token punctuation">;</span>

  <span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span>width > 600px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
    <span class="token property">grid-template-columns</span><span class="token punctuation">:</span> <span class="token function">repeat</span><span class="token punctuation">(</span>5<span class="token punctuation">,</span> 1fr<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<div class="at-g-feature">
<p class="codepen" data-height="500" data-default-tab="result" data-slug-hash="bNdMBbG" data-pen-title="gap rule swap (full)" data-user="sturobson" data-token="0552bb39286e4a4efe295e0d81fea4c2" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sturobson/pen/bNdMBbG/0552bb39286e4a4efe295e0d81fea4c2">
  gap rule swap (full)</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>
</div>
<p>By default (on narrow screens), our grid has a single column with five rows, showing the horizontal rules between logos. Once the viewport is wider than 600px, it transforms into a five-column grid with a single row, now showing vertical rules between logos instead.</p>
<p>The beauty of using gap decorations here is that we don't need to worry about which rules show when... the browser handles that for us based on the layout. When there's only one column, column rules aren't visible, and when there's only one row, row rules aren't visible.</p>
<p>Since we're using the same width, style, and color for both our row and column rules, we can simplify our CSS even further using the <code>⁠rule</code> shorthand property:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">ul</span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span>
  <span class="token property">gap</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">justify-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>

  <span class="token property">rule</span><span class="token punctuation">:</span> 1px solid black<span class="token punctuation">;</span>

  <span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span>width > 600px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
    <span class="token property">grid-template-columns</span><span class="token punctuation">:</span> <span class="token function">repeat</span><span class="token punctuation">(</span>5<span class="token punctuation">,</span> 1fr<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>This single line of ⁠<code>rule: 1px solid black</code> replaces our previous six lines of individual properties, making our code more concise while maintaining the same responsive behavior. The browser still handles the visibility of rules based on the layout, we've just made it more efficient to write.</p>
<div class="at-g-feature">
<p class="codepen" data-height="500" data-default-tab="result" data-slug-hash="YPwapgM" data-pen-title="gap rule swap (simplified)" data-user="sturobson" data-token="595ae580e4a2b3c3f934ee42e502d580" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sturobson/pen/YPwapgM/595ae580e4a2b3c3f934ee42e502d580">
  gap rule swap (simplified)</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>
</div>
<h2 id="advanced-gap-decorations" tabindex="-1">Advanced Gap Decorations</h2>
<p>Building on the basic gap decorations, we can create more sophisticated visual patterns and layouts. Here are some advanced techniques that leverage the full power of CSS gap decorations:</p>
<h3 id="non-uniform-gap-patterns" tabindex="-1">Non-uniform Gap Patterns</h3>
<p>Instead of applying the same decoration to every gap, we can create rhythmic patterns or highlight specific sections:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.feature-grid</span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span>
  <span class="token property">grid-template-columns</span><span class="token punctuation">:</span> <span class="token function">repeat</span><span class="token punctuation">(</span>3<span class="token punctuation">,</span> 1fr<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">gap</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>

  <span class="token comment">/* Create alternating pattern for column rules */</span>
  <span class="token property">column-rule</span><span class="token punctuation">:</span> 1px solid black<span class="token punctuation">;</span>
  <span class="token property">column-rule-width</span><span class="token punctuation">:</span> 1px 2px<span class="token punctuation">;</span> <span class="token comment">/* Alternates between 1px and 2px */</span>

  <span class="token comment">/* Apply dotted style to every third row */</span>
  <span class="token property">row-rule</span><span class="token punctuation">:</span> 1px solid black<span class="token punctuation">;</span>
  <span class="token property">row-rule-style</span><span class="token punctuation">:</span> solid solid dotted<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="visually-distinct-sections" tabindex="-1">Visually Distinct Sections</h3>
<p>You can create visual hierarchy by applying different gap decorations to specific grid areas:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.dashboard</span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span>
  <span class="token property">grid-template</span><span class="token punctuation">:</span>
    <span class="token string">'header header header'</span> auto
    <span class="token string">'sidebar main main'</span> 1fr
    <span class="token string">'footer footer footer'</span> auto / 1fr 1fr 1fr<span class="token punctuation">;</span>
  <span class="token property">gap</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>

  <span class="token comment">/* Base gap style */</span>
  <span class="token property">row-rule</span><span class="token punctuation">:</span> 1px solid #ddd<span class="token punctuation">;</span>
  <span class="token property">column-rule</span><span class="token punctuation">:</span> 1px solid #ddd<span class="token punctuation">;</span>

  <span class="token comment">/* Custom gap between header and content */</span>
  <span class="token property">row-rule-width</span><span class="token punctuation">:</span> 3px 1px<span class="token punctuation">;</span>
  <span class="token property">row-rule-color</span><span class="token punctuation">:</span> #0074d9 #ddd<span class="token punctuation">;</span>

  <span class="token comment">/* No vertical divider between main sections */</span>
  <span class="token property">column-rule-width</span><span class="token punctuation">:</span> 1px 0px 1px<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="decorative-gap-elements" tabindex="-1">Decorative Gap Elements</h3>
<p>For truly custom gap decorations, we can position decorative elements in the gap space:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.gallery-grid</span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span>
  <span class="token property">grid-template-columns</span><span class="token punctuation">:</span> <span class="token function">repeat</span><span class="token punctuation">(</span>3<span class="token punctuation">,</span> 1fr<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">gap</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span>
  <span class="token property">position</span><span class="token punctuation">:</span> relative<span class="token punctuation">;</span>

  <span class="token comment">/* Create space for decorations */</span>
  <span class="token property">row-rule-outset</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">column-rule-outset</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>

  <span class="token comment">/* Visible rule styles */</span>
  <span class="token property">row-rule</span><span class="token punctuation">:</span> 1px dashed #0074d9<span class="token punctuation">;</span>
  <span class="token property">column-rule</span><span class="token punctuation">:</span> 1px dashed #0074d9<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Add decorative elements at intersections */</span>
<span class="token selector">.gallery-grid .gallery-item</span> <span class="token punctuation">{</span>
  <span class="token property">position</span><span class="token punctuation">:</span> relative<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Add corner decorations to create the appearance of decorated gaps */</span>
<span class="token selector">.gallery-grid .gallery-item::after</span> <span class="token punctuation">{</span>
  <span class="token property">content</span><span class="token punctuation">:</span> <span class="token string">''</span><span class="token punctuation">;</span>
  <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
  <span class="token property">background</span><span class="token punctuation">:</span>
    <span class="token function">radial-gradient</span><span class="token punctuation">(</span>circle at center<span class="token punctuation">,</span> #0074d9 0.25rem<span class="token punctuation">,</span> transparent 0.25rem<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">repeating-linear-gradient</span><span class="token punctuation">(</span>
      45deg<span class="token punctuation">,</span>
      #0074d9 0<span class="token punctuation">,</span>
      #0074d9 2px<span class="token punctuation">,</span>
      transparent 2px<span class="token punctuation">,</span>
      transparent 8px
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> 50%<span class="token punctuation">;</span>
  <span class="token property">bottom</span><span class="token punctuation">:</span> -1.75rem<span class="token punctuation">;</span>
  <span class="token property">right</span><span class="token punctuation">:</span> -1.75rem<span class="token punctuation">;</span>
  <span class="token property">z-index</span><span class="token punctuation">:</span> 2<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Hide decorations on last column (every 3rd item) */</span>
<span class="token selector">.gallery-grid .gallery-item:nth-child(3n)::after</span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* Hide decorations on last row */</span>
<span class="token selector">.gallery-grid .gallery-item:nth-last-child(-n + 3)::after</span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="theme-aware-gap-decorations" tabindex="-1">Theme-Aware Gap Decorations</h3>
<p>Using CSS custom properties, we can make gap decorations respond to theme changes:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--gap-primary-color</span><span class="token punctuation">:</span> #0074d9<span class="token punctuation">;</span>
  <span class="token property">--gap-secondary-color</span><span class="token punctuation">:</span> #ddd<span class="token punctuation">;</span>
  <span class="token property">--gap-width-small</span><span class="token punctuation">:</span> 1px<span class="token punctuation">;</span>
  <span class="token property">--gap-width-large</span><span class="token punctuation">:</span> 3px<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.dark-theme</span> <span class="token punctuation">{</span>
  <span class="token property">--gap-primary-color</span><span class="token punctuation">:</span> #61dafb<span class="token punctuation">;</span>
  <span class="token property">--gap-secondary-color</span><span class="token punctuation">:</span> #444<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.content-sections</span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span>
  <span class="token property">grid-template-columns</span><span class="token punctuation">:</span> <span class="token function">repeat</span><span class="token punctuation">(</span>2<span class="token punctuation">,</span> 1fr<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">gap</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>

  <span class="token comment">/* Theme-aware gap decorations */</span>
  <span class="token property">column-rule</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--gap-width-small<span class="token punctuation">)</span> solid <span class="token function">var</span><span class="token punctuation">(</span>--gap-secondary-color<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">row-rule</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--gap-width-large<span class="token punctuation">)</span> dotted <span class="token function">var</span><span class="token punctuation">(</span>--gap-primary-color<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">/* Different outset based on theme */</span>
  <span class="token property">row-rule-outset</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--gap-width-large<span class="token punctuation">)</span> * 2<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Here’s a handy CodePen demonstrating the above examples, in action:</p>
<div class="at-g-feature">
<p class="codepen" data-height="500" data-default-tab="result" data-slug-hash="raxdjzZ" data-pen-title="CSS gap decoration 'advanced' examples" data-user="sturobson" data-token="b1208e43a1ff0c006cd9ab2fc8ee1313" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sturobson/pen/raxdjzZ/b1208e43a1ff0c006cd9ab2fc8ee1313">
  CSS gap decoration 'advanced' examples</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>
</div>
<h2 id="browser-support" tabindex="-1">Browser Support</h2>
<p>Lacklustre to say the least. Currently, as I write this, styling gaps only works for Chromium-based browsers. You can see <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1963897">the work the Firefox team are doing on this here</a> and <a href="https://bugs.webkit.org/show_bug.cgi?id=298551">where Webkit is up to here</a>.</p>
<p>However, since this is a purely decorative feature (as the specification name suggests), I think we can confidently use it without worrying about browsers that don't yet support it. Non-supporting browsers will simply display layouts without the gap decorations, which doesn't impact functionality.</p>
<p>And it's 2025, just as we recognised in 2012, websites don't need to look identical in every browser. Embracing the platform's natural progressive enhancement capabilities remains as valid as ever.</p>
<h2 id="wrapping-up" tabindex="-1">Wrapping Up</h2>
<p>Gap decorations solve a problem I've been wrestling with since 2017, and now we have an elegant, declarative solution. No more pseudo-elements. No more magic numbers. Just straightforward CSS that adapts to your layout.</p>
<p>The familiar border-like syntax makes it approachable, while features like rule-outset and pattern creation give us room to get creative.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Context‑Aware Cornering: How inherit() Can Simplify Border‑Radius for Components</title>
      <link href="https://www.alwaystwisted.com/articles/making-context-aware-corners.html"/>
      <updated>2025-10-21T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/making-context-aware-corners.html</id>
      <content type="html">
        <![CDATA[
        <p>Whilst I was working on my <a href="https://www.alwaystwisted.com/articles/making-context-aware-components">last article about the new <code>inherit()</code> CSS function</a> I looked at how we could use this to help simplify the border radius of child elements based on what the parent element had. But, I’d completely forgot about it when I started to write that article so, as a ‘bonus’, I thought I’d quickly write it up here.</p>
<h2 id="the-design-problem" tabindex="-1">The Design Problem</h2>
<p>Rounded corners can be a small design detail, but they matter. When you nest elements, like a card with padding containing an inner panel with its own background and then a button inside that, the inner corners can easily look out of whack. The inner corners could appear to too small or too large and fail to look part of a overall consistent design.</p>
<p>Designers want a consistent visual rhythm across any nester layers and site visitors can see this visual consistency as a way to ‘trust’ the site they’re using. Yet, different contexts may change the padding and radius means keeping control of the values to make it visually consistent quite tedious.</p>
<p>The design goal here is pretty simple: nested elements should visually respect the parent border radius (corner) so the UI looks cohesive without the need to add lots of extra design tokens or per-component overrides.</p>
<h2 id="how-teams-work-it-out-now" tabindex="-1">How teams work it out now</h2>
<h3 id="parent-publishes-derived-values" tabindex="-1">Parent publishes derived values</h3>
<p>The parent computes and publishes derived variable, for example <code>⁠--inner-radius</code> and <code>⁠--btn-radius</code>, and children read those with ⁠<code>var()</code>. This is explicit and compatible, but it pushes the responsibility to the parent and increases the amount of design tokens and/or Sass variables / CSS Custom Properties you’ll need to create.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.card</span> <span class="token punctuation">{</span>
  <span class="token property">--card-radius</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
  <span class="token property">--card-padding</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--inner-radius</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--card-radius<span class="token punctuation">)</span> - <span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--card-padding<span class="token punctuation">)</span> * 0.5<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--btn-radius</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--inner-radius<span class="token punctuation">)</span> - <span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--card-padding<span class="token punctuation">)</span> * 0.25<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-padding<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__inner</span> <span class="token punctuation">{</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--inner-radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.btn</span> <span class="token punctuation">{</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--btn-radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="each-layer-computes-locally-from-published-base-variables" tabindex="-1">Each layer computes locally from published base variables</h3>
<p>The parent publishes base variables (⁠<code>—card-radius</code>, <code>⁠--card-padding</code>). Each child computes its own value using <code>⁠var()</code> and <code>⁠calc()</code>. This keeps the parent API smaller but requires each child to know the math.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.card</span> <span class="token punctuation">{</span>
  <span class="token property">--card-radius</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
  <span class="token property">--card-padding</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__inner</span> <span class="token punctuation">{</span>
  <span class="token property">--inner-radius</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--card-radius<span class="token punctuation">)</span> - <span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--card-padding<span class="token punctuation">)</span> * 0.5<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--inner-radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.btn</span> <span class="token punctuation">{</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--inner-radius<span class="token punctuation">)</span> - <span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--card-padding<span class="token punctuation">)</span> * 0.25<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="build-time-expansion-using-sass" tabindex="-1">Build-time expansion using Sass</h3>
<p>If you want reliable output that works in all browsers and avoids runtime arithmetic, generate the derived radius at build time and emit explicit CSS variables (or classes) for each variant. Sass is a convenient place to do this: generate card variants from a spacing and radius scale, compute inner and button radii using your chosen rules, and output the variables on the card (or as utility classes).</p>
<h4 id="define-your-base-scales-(spacing-and-radius)" tabindex="-1">Define your base scales (spacing and radius)</h4>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$spacing</span></span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
  <span class="token property">100</span><span class="token punctuation">:</span> 0.25rem<span class="token punctuation">,</span>
  <span class="token property">200</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">,</span>
  <span class="token property">300</span><span class="token punctuation">:</span> 0.75rem<span class="token punctuation">,</span>
  <span class="token property">400</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">,</span>
  <span class="token property">500</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token property"><span class="token variable">$radius</span></span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
  <span class="token property">sm</span><span class="token punctuation">:</span> 0.375rem<span class="token punctuation">,</span>
  <span class="token property">md</span><span class="token punctuation">:</span> 0.75rem<span class="token punctuation">,</span>
  <span class="token property">lg</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h4 id="create-a-function-for-the-calculations" tabindex="-1">Create a function for the calculations</h4>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@function</span> <span class="token function">inner-radius</span><span class="token punctuation">(</span><span class="token variable">$outer-radius</span><span class="token punctuation">,</span> <span class="token variable">$pad</span><span class="token punctuation">,</span> <span class="token property"><span class="token variable">$factor</span></span><span class="token punctuation">:</span> 0.5<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token property"><span class="token variable">$result</span></span><span class="token punctuation">:</span> <span class="token variable">$outer-radius</span> <span class="token operator">-</span> <span class="token punctuation">(</span><span class="token variable">$pad</span> <span class="token operator">*</span> <span class="token variable">$factor</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">@if</span> <span class="token selector"><span class="token variable">$result</span> &lt;= 0 </span><span class="token punctuation">{</span>
    <span class="token keyword">@return</span> 0rem<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">@return</span> <span class="token variable">$result</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">@function</span> <span class="token function">grandchild-radius</span><span class="token punctuation">(</span><span class="token variable">$parent-radius</span><span class="token punctuation">,</span> <span class="token variable">$pad</span><span class="token punctuation">,</span> <span class="token property"><span class="token variable">$factor</span></span><span class="token punctuation">:</span> 0.25<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token property"><span class="token variable">$result</span></span><span class="token punctuation">:</span> <span class="token variable">$parent-radius</span> <span class="token operator">-</span> <span class="token punctuation">(</span><span class="token variable">$pad</span> <span class="token operator">*</span> <span class="token variable">$factor</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">@if</span> <span class="token selector"><span class="token variable">$result</span> &lt;= 0 </span><span class="token punctuation">{</span>
    <span class="token keyword">@return</span> 0rem<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">@return</span> <span class="token variable">$result</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="create-a-mixin-that-can-generate-the-variables" tabindex="-1">Create a mixin that can generate the variables</h4>
<pre class="language-scss"><code class="language-scss"><span class="token comment">// Generic mixin: create radii for a parent element.</span>
<span class="token comment">// - Creates --parent-radius and --parent-pad (base tokens)</span>
<span class="token comment">// - Creates --inner-radius (derived from parent)</span>
<span class="token comment">// - Creates --grandchild-radius (derived from inner and pad)</span>
<span class="token keyword">@mixin</span> <span class="token function">derived-radii</span><span class="token punctuation">(</span>
  <span class="token variable">$parent-radius</span><span class="token punctuation">,</span>
  <span class="token variable">$parent-pad</span><span class="token punctuation">,</span>
  <span class="token property"><span class="token variable">$inner-factor</span></span><span class="token punctuation">:</span> 0.5<span class="token punctuation">,</span>
  <span class="token property"><span class="token variable">$grandchild-factor</span></span><span class="token punctuation">:</span> 0.25
<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// expose base tokens on the element</span>
  <span class="token property">--parent-radius</span><span class="token punctuation">:</span> <span class="token variable">#{$parent-radius}</span><span class="token punctuation">;</span>
  <span class="token property">--parent-pad</span><span class="token punctuation">:</span> <span class="token variable">#{$parent-pad}</span><span class="token punctuation">;</span>

  <span class="token comment">// compute values at build time and create them as CSS variables</span>
  <span class="token property"><span class="token variable">$inner</span></span><span class="token punctuation">:</span> <span class="token function">inner-radius</span><span class="token punctuation">(</span><span class="token variable">$parent-radius</span><span class="token punctuation">,</span> <span class="token variable">$parent-pad</span><span class="token punctuation">,</span> <span class="token variable">$inner-factor</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--inner-radius</span><span class="token punctuation">:</span> <span class="token variable">#{$inner}</span><span class="token punctuation">;</span>

  <span class="token property"><span class="token variable">$grand</span></span><span class="token punctuation">:</span> <span class="token function">grandchild-radius</span><span class="token punctuation">(</span><span class="token variable">$inner</span><span class="token punctuation">,</span> <span class="token variable">$parent-pad</span><span class="token punctuation">,</span> <span class="token variable">$grandchild-factor</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--grandchild-radius</span><span class="token punctuation">:</span> <span class="token variable">#{$grand}</span><span class="token punctuation">;</span>

  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--parent-radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--parent-pad<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="example-using-a-card-with-a-child-(card__inner)-and-grandchild-(.btn)" tabindex="-1">Example using a card with a child (<code>card__inner</code>) and grandchild (<code>.btn</code>)</h4>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.card </span><span class="token punctuation">{</span>
  <span class="token property">--parent-radius</span><span class="token punctuation">:</span> 0.75rem<span class="token punctuation">;</span>
  <span class="token property">--parent-pad</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--parent-radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--parent-pad<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* apply mixin for one variant */</span>
<span class="token selector">.card--lg-400 </span><span class="token punctuation">{</span>
  <span class="token keyword">@include</span> <span class="token function">derived-radii</span><span class="token punctuation">(</span><span class="token function">map-get</span><span class="token punctuation">(</span><span class="token variable">$radius</span><span class="token punctuation">,</span> lg<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">map-get</span><span class="token punctuation">(</span><span class="token variable">$spacing</span><span class="token punctuation">,</span> 400<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__inner </span><span class="token punctuation">{</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--inner-radius<span class="token punctuation">,</span> 0.5rem<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--parent-pad<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span> <span class="token operator">*</span> 0.5<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__inner .btn </span><span class="token punctuation">{</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--grandchild-radius<span class="token punctuation">,</span> 0.375rem<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="generated-css" tabindex="-1">Generated CSS</h4>
<pre class="language-css"><code class="language-css"><span class="token selector">.card</span> <span class="token punctuation">{</span>
  <span class="token property">--parent-radius</span><span class="token punctuation">:</span> 0.75rem<span class="token punctuation">;</span>
  <span class="token property">--parent-pad</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--parent-radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--parent-pad<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card--lg-400</span> <span class="token punctuation">{</span>
  <span class="token property">--parent-radius</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
  <span class="token property">--parent-pad</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--inner-radius</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--grandchild-radius</span><span class="token punctuation">:</span> 0.75rem<span class="token punctuation">;</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--parent-radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--parent-pad<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__inner</span> <span class="token punctuation">{</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--inner-radius<span class="token punctuation">,</span> 0.5rem<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--parent-pad<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span> * 0.5<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__inner .btn</span> <span class="token punctuation">{</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--grandchild-radius<span class="token punctuation">,</span> 0.375rem<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="what-inherit()-is-(recap)" tabindex="-1">What inherit() is (recap)</h2>
<p>As mentioned in the previous article, <code>⁠inherit()</code> is a working draft CSS Values Level 5 function that will substitute the parent element's computed custom-property</p>
<pre class="language-css"><code class="language-css"><span class="token function">inherit</span><span class="token punctuation">(</span>--foo<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span></code></pre>
<p>It returns the parent’s computed value for ⁠<code>--foo</code>. If the immediate parent does not set it, it comes from the nearest ancestor. The second argument is an optional fallback used when the inherited value is invalid.
Using <code>inherit()</code> lets the component say &quot;trust my parent to decide, I'll work it out from there.”. Using <code>var()</code> says &quot;I want this specific token.&quot;</p>
<h2 id="making-context-aware-corners-with-inherit()" tabindex="-1">Making Context-Aware Corners with inherit()</h2>
<p>With ⁠<code>inherit()</code> each component can perform the math locally, reading exactly what the parent resolved. The child expresses how it wants to be inset relative to its parent. Let’s take a card as an example, which has an inner panel and a button.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>article</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>card<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>card__inner<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Action<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>article</span><span class="token punctuation">></span></span></code></pre>
<pre class="language-css"><code class="language-css"><span class="token selector">.card</span> <span class="token punctuation">{</span>
  <span class="token property">--card-radius</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
  <span class="token property">--card-padding</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>

  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-padding<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* inner computes its radius directly from the parent's computed values */</span>
<span class="token selector">.card__inner</span> <span class="token punctuation">{</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>
    <span class="token function">inherit</span><span class="token punctuation">(</span>--card-radius<span class="token punctuation">,</span> 1.5rem<span class="token punctuation">)</span> - <span class="token punctuation">(</span><span class="token function">inherit</span><span class="token punctuation">(</span>--card-padding<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span> * 0.5<span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">inherit</span><span class="token punctuation">(</span>--card-padding<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span> * 0.5<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* button computes its radius from the inner's computed result and the card pad */</span>
<span class="token selector">.btn</span> <span class="token punctuation">{</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>
    <span class="token function">inherit</span><span class="token punctuation">(</span>--card-radius<span class="token punctuation">,</span> 1.5rem<span class="token punctuation">)</span> -
      <span class="token punctuation">(</span><span class="token function">inherit</span><span class="token punctuation">(</span>--card-padding<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span> * <span class="token punctuation">(</span>0.5 + 0.25<span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token property">padding</span><span class="token punctuation">:</span> 0.5rem 1rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p><code>inherit(--card-radius)</code> reads the parent element’s computed <code>--card-radius</code>. If the parent computes a local alias (for example <code>—card-pad: calc(var(--gap) * 0.75)</code>), <code>inherit()</code> returns that computed result rather than performing a raw token lookup. All <code>inherit()</code> calls in the examples include fallbacks so styles remain predictable when a token is missing or when the feature is not supported.
Here's that example in action:</p>
<div class="at-g-feature">
<p class="codepen" data-height="500" data-default-tab="result" data-slug-hash="jErYRzQ" data-pen-title="Untitled" data-user="sturobson" data-token="39baf61023110300790c4e63a73bc3e8" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
      <span>See the Pen <a href="https://codepen.io/sturobson/pen/jErYRzQ/39baf61023110300790c4e63a73bc3e8">
  Untitled</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
      </p>
      <script async src="https://public.codepenassets.com/embed/index.js"></script>
</div>
<h2 id="bonus%2C-grandchildren-and-cleaner-code." tabindex="-1">Bonus, grandchildren and cleaner code.</h2>
<p>For many components it’s cleaner for the inner element to compute and publish a single derived value and for grandchildren to consume that value. The inner computes <code>--inner-radius</code> using <code>inherit()</code> and a local <code>calc()</code>, then publishes it; grandchildren read that value to compute their own corners. This keeps the math in one place and makes intent explicit.</p>
<p>To keep values safe, include sensible fallbacks in your <code>inherit()</code> calls (for example <code>inherit(--outer-pad, 1rem)</code>) and publish reasonable defaults at the parent level so children receive predictable inputs. When appropriate, use <code>clamp()</code> to constrain results; alternatively generate safe derived values at build time (Sass) or have the parent publish an explicit <code>--inner-radius</code> when a guaranteed non‑negative value is required. These approaches avoid duplicated math while keeping runtime behaviour predictable.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.outer</span> <span class="token punctuation">{</span>
  <span class="token property">--outer-radius</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
  <span class="token property">--outer-pad</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--outer-radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--outer-pad<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.inner</span> <span class="token punctuation">{</span>
  <span class="token property">--inner-radius</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>
    <span class="token function">inherit</span><span class="token punctuation">(</span>--outer-radius<span class="token punctuation">,</span> 1.5rem<span class="token punctuation">)</span> - <span class="token punctuation">(</span><span class="token function">inherit</span><span class="token punctuation">(</span>--outer-pad<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span> * 0.5<span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--inner-radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">inherit</span><span class="token punctuation">(</span>--outer-pad<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span> * 0.5<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.btn</span> <span class="token punctuation">{</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>
    <span class="token function">inherit</span><span class="token punctuation">(</span>--inner-radius<span class="token punctuation">,</span> 0.75rem<span class="token punctuation">)</span> - <span class="token punctuation">(</span><span class="token function">inherit</span><span class="token punctuation">(</span>--outer-pad<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span> * 0.25<span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="why-this-may-be-better" tabindex="-1">Why this may be better</h3>
<p>Using ⁠<code>inherit()</code> here shifts ownership: parents publish base variables (radius, padding) and components declare how they want to derive values from their parent. That reduces variable surface area and avoids pushing many derived values onto the parent. It also makes components resilient to parent-side transforms, if the parent computes an alias or applies clamp/scale, children using ⁠<code>inherit()</code> follow the computed result.</p>
<p>Components also become resilient to parent-side transforms. If a parent computes an alias or applies clamp or scaling, children using ⁠inherit() automatically follow the parent’s computed value. The result is cleaner, more self-documenting component CSS: the relationship (calculate from parent) is explicit in the component, and derived definitions are not scattered across the codebase.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Making Context-Aware Components: How CSS inherit() Could Simplify Design Systems</title>
      <link href="https://www.alwaystwisted.com/articles/making-context-aware-components.html"/>
      <updated>2025-10-16T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/making-context-aware-components.html</id>
      <content type="html">
        <![CDATA[
        <p>Spotted on social media an ‘intent to ship’ post from the Blink team for a new <code>inherit()</code> CSS function. A quick read of what is within <a href="https://chromestatus.com/feature/5996914579472384?gate=4828748570558464">the Chrome Platform Status post</a>, and what was in <a href="https://drafts.csswg.org/css-values-5/#inherit-notation">the W3C specification</a> had my mind buzzing on how this can help us to build better, more ‘context aware’ components for our Design Systems moving forward.</p>
<p>So, with some coffee and the ideas popping I thought I’d write a short post on the <a href="https://www.google.com/url?sa=t&amp;source=web&amp;rct=j&amp;opi=89978449&amp;url=https://www.imdb.com/title/tt1131921/&amp;ved=2ahUKEwjQpdGOzqiQAxVYU0EAHZg7DJAQFnoECBkQAQ&amp;usg=AOvVaw3TRGBRY4RaO1GnnR54nKPf">Johnny Ball</a> of it all.</p>
<p>CSS custom properties already let developers expose and use values from a Design System (often surfaced as design tokens). A child element can read a value set on an ancestor simply by referencing the same custom property via the cascade, but that isn’t a direct way to reference the parent’s computed custom property for in‑place derivation. The new <code>inherit()</code> function looks to help fill that gap. It will explicitly take the parent element’s computed custom‑property value so the child can derive a related value (for example, scale, offset, or colour mix) relative to the parent without duplicating tokens or relying on extra overrides.</p>
<p><code>inherit()</code> is a <a href="https://drafts.csswg.org/css-values-5/">CSS Values Level 5</a> feature that reads a parent’s computed custom property (with an optional fallback, e.g. <code>inherit(--foo, 16px)</code>). It returns the parent’s resolved value, and if the immediate parent doesn’t set one, the value comes from the nearest ancestor that does.</p>
<p>This parent-focused behaviour could be exactly what design systems need: components can derive spacing, density, colour and motion from their container, so you avoid duplicating tokens and get a predictable, context-aware user interface.</p>
<h2 id="but%2C-why-not-make-more-custom-properties%3F" tabindex="-1">But, why not make more custom properties?</h2>
<p>It’s tempting to create Design Tokens for everything you think you’d ever need and add bespoke custom properties everywhere, but inherit() could give us a cleaner alternative. Rather than proliferating tokens, derive local values from a small set of region-level properties so components can stay simple and predictable.</p>
<ul>
<li>A single source of truth: Region or page tokens (spacing, density, accent, motion) stay authoritative; components derive what they need instead of duplicating tokens.</li>
<li>Context‑aware defaults: Components can adapt to their container (compact toolbar vs spacious area), padding, size and spacing update with no extra classes or JS.</li>
<li>Fewer overrides: Set one token on a wrapper and everything inside can adapt with it, avoiding many special-case rules or variants.</li>
</ul>
<h2 id="a-practical-example%2C-making-%E2%80%9Cthe-card%E2%80%9D%3A-from-custom-properties-to-inherit()" tabindex="-1">A practical example, making “the card”: from custom properties to <code>inherit()</code></h2>
<p>Let’s look at a focused example where we can replace a multitude of bespoke custom properties with the new <code>inherit()</code> function.</p>
<p>First, let’s take a simple card component:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>article</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>card<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>card__content<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h2</span><span class="token punctuation">></span></span>A Card Title<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h2</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>
      Lorem ipsum, dolor sit amet consectetur adipisicing elit. Unde tempore
      veritatis illum voluptas.
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Click here<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>article</span><span class="token punctuation">></span></span></code></pre>
<p>And traditionally (however, more common recently) we would make use of existing custom properties in our code (perhaps from Design Tokens), something like:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--spacing-200</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-400</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-600</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="custom-properties-everywhere" tabindex="-1">Custom Properties Everywhere</h3>
<p>The first version of our card will set every spacing value explicitly with a custom property.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.card</span> <span class="token punctuation">{</span>
  <span class="token property">--card-spacing</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-400<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--card-gap</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-200<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--card-heading-gap</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-400<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-spacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__content > * + *</span> <span class="token punctuation">{</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-gap<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__content h2 + *</span> <span class="token punctuation">{</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-heading-gap<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="one-custom-property-to-rule-all-spacing" tabindex="-1">One Custom Property to rule all spacing</h3>
<p>We could tidy this up and reduce the duplication of custom properties inside the card by using some maths. The relationships are now explicit but also local.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.card</span> <span class="token punctuation">{</span>
  <span class="token property">--card-spacing</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-400<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token property">max-width</span><span class="token punctuation">:</span> 300px<span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-spacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">border</span><span class="token punctuation">:</span> 1px solid #000<span class="token punctuation">;</span>
  <span class="token property">background</span><span class="token punctuation">:</span> #fff<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__content > * + *</span> <span class="token punctuation">{</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--card-spacing<span class="token punctuation">)</span> * 0.5<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__content h2 + *</span> <span class="token punctuation">{</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-spacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="or-we-could-start-using-inherit()" tabindex="-1">Or we could start using <code>inherit()</code></h4>
<pre class="language-css"><code class="language-css"><span class="token selector">.card</span> <span class="token punctuation">{</span>
  <span class="token property">--card-spacing</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-400<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token property">max-width</span><span class="token punctuation">:</span> 300px<span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">inherit</span><span class="token punctuation">(</span>--card-spacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">border</span><span class="token punctuation">:</span> 1px solid #000<span class="token punctuation">;</span>
  <span class="token property">background</span><span class="token punctuation">:</span> #fff<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__content > * + *</span> <span class="token punctuation">{</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">inherit</span><span class="token punctuation">(</span>--card-spacing<span class="token punctuation">)</span> * 0.5<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__content h2 + *</span> <span class="token punctuation">{</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> <span class="token function">inherit</span><span class="token punctuation">(</span>--card-spacing<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>You can swap <code>var()</code> for <code>inherit()</code> here, but doing so on the card itself is redundant unless the parent provides a token.</p>
<h3 id="inheriting-from-the-parent" tabindex="-1">Inheriting from the parent</h3>
<p>Where this could truly be revolutionary on how we author CSS in component libraries and Design Systems is when can make use of an element’s parent custom properties. Say we have a generic <a href="http://containerist.org/">container</a> regions that has three padding options.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--spacing-200</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-400</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-600</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.region--compact</span> <span class="token punctuation">{</span>
  <span class="token property">--gap</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-200<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.region--default</span> <span class="token punctuation">{</span>
  <span class="token property">--gap</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-400<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.region--comfortable</span> <span class="token punctuation">{</span>
  <span class="token property">--gap</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-600<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>With <code>inherit()</code> we can make use of the <code>--gap</code> custom property so that our cards match the look and feel of the parent container.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.card</span> <span class="token punctuation">{</span>
  <span class="token comment">/* this will inherit from the parent --gap value */</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">inherit</span><span class="token punctuation">(</span>--gap<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__content > * + *</span> <span class="token punctuation">{</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">inherit</span><span class="token punctuation">(</span>--gap<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span> * 0.5<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__content h2 + *</span> <span class="token punctuation">{</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> <span class="token function">inherit</span><span class="token punctuation">(</span>--gap<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>The container region sets the <code>--gap</code>, the card makes use of it with <code>inherit()</code>, cards inside <code>.region--compact</code> become tighter, those in <code>.region--comfortable</code> become more spacious <strong>automatically</strong>. There are no ‘per card’ overrides like <code>.card--compact</code> or <code>.card--comfortable</code> required.</p>
<p>We could, although I think it would make things more complex, also mix all options together. Making use of <code>inherit()</code> for context-aware design decisions and local component specific custom properties.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--spacing-200</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-400</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-600</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.region--compact</span> <span class="token punctuation">{</span>
  <span class="token property">--gap</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-200<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.region--default</span> <span class="token punctuation">{</span>
  <span class="token property">--gap</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-400<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.region--comfortable</span> <span class="token punctuation">{</span>
  <span class="token property">--gap</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-600<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card</span> <span class="token punctuation">{</span>
  <span class="token property">--card-pad</span><span class="token punctuation">:</span> <span class="token function">inherit</span><span class="token punctuation">(</span>--gap<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--card-gap</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">inherit</span><span class="token punctuation">(</span>--gap<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span> * 0.5<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--card-heading-gap</span><span class="token punctuation">:</span> <span class="token function">inherit</span><span class="token punctuation">(</span>--gap<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-pad<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__content > * + *</span> <span class="token punctuation">{</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-gap<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.card__content h2 + *</span> <span class="token punctuation">{</span>
  <span class="token property">margin-top</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-heading-gap<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="choices-and-fallbacks" tabindex="-1">Choices and Fallbacks</h3>
<p>When you adopt <code>⁠inherit()</code> treat CSS custom properties as the runtime surface your components read from — not the canonical design-token source. Keep the runtime surface small: expose a few region-level properties that express layout and theme intent, and let components derive their implementation values from those.</p>
<p>At the region level expose a tight set of properties for values that change by context: <code>—gap</code>, <code>—density</code>, <code>—base-size</code>, <code>—accent</code>. These are the values components should inherit from their container and treat as authoritative for regional behaviour.</p>
<p>Inside components, keep implementation property names scoped and minimal (for example <code>—card-gap</code>, <code>—btn-pad</code>, <code>—chip-accent</code>). Derive those values from the nearest ancestor using ⁠<code>inherit()</code> rather than adding new global properties. Example:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.card</span> <span class="token punctuation">{</span>
  <span class="token comment">/* derive a card-scoped value from the region token */</span>
  <span class="token property">--card-gap</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">inherit</span><span class="token punctuation">(</span>--gap<span class="token punctuation">,</span> 16px<span class="token punctuation">)</span> * 0.75<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-gap<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Use consistent units (<code>rem</code> or <code>px</code>) so <code>⁠calc()</code> is predictable, and include sensible fallbacks in <code>⁠inherit()</code> so components work when a region property is missing or in older browsers. Document ownership: list which properties belong on root, which on page/region wrappers, and which are component implementation details. That keeps naming clear and makes it obvious what <code>⁠inherit()</code> will read and what components compute.</p>
<h2 id="dealing-with-non%E2%80%91supporting-browsers" tabindex="-1">Dealing with non‑supporting browsers</h2>
<p><code>inherit()</code> will be a runtime cascade feature and support will vary while browsers implement it. The goal of any front-end developer is to make components that behave well everywhere today while progressively enhancing where CSS features like <code>inherit()</code> become available.</p>
<p>Here’s a couple of ways to approach using <code>inherit()</code></p>
<p>We could use <code>@supports()</code> to detect the lack of <code>inherit()</code> and provide a simple fallback path.</p>
<pre class="language-css"><code class="language-css"><span class="token atrule"><span class="token rule">@supports</span> <span class="token punctuation">(</span><span class="token keyword">not</span> <span class="token punctuation">(</span><span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token function">inherit</span><span class="token punctuation">(</span>--gap<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
  <span class="token selector">.card</span> <span class="token punctuation">{</span>
    <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--fallback-card-pad<span class="token punctuation">,</span> 12px<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>We could provide some defaults first and then place the <code>inherit()</code> rule afterwards</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.card</span> <span class="token punctuation">{</span>
  <span class="token comment">/* baseline for old browsers */</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-pad<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">/* enhanced when inherit() is available (overrides the baseline) */</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">inherit</span><span class="token punctuation">(</span>--gap<span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--card-pad<span class="token punctuation">,</span> 1rem<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="where-to-%22%2B1%22-implementation" tabindex="-1">Where to &quot;+1&quot; implementation</h2>
<p>If you want this CSS feature implemented into web browsers you can upvote them here:</p>
<ul>
<li><a href="https://issues.chromium.org/issues/452071846">Chromium</a></li>
<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1994658">Firefox</a></li>
<li>Safari (not available yet)</li>
</ul>
<h2 id="to-end%E2%80%A6" tabindex="-1">To end…</h2>
<p>The new <code>inherit()</code> CSS feature can make your components naturally context-aware. For Design Systems I think it promises the opportunity for fewer design tokens, fewer overrides and simpler CSS-first adaptations to layouts, typography, theming, and motion.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>... and that&#39;s my rank!</title>
      <link href="https://www.alwaystwisted.com/articles/and-thats-my-rank.html"/>
      <updated>2025-10-16T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/and-thats-my-rank.html</id>
      <content type="html">
        <![CDATA[
        <p>I was quite excited and intrigued last Friday when I spotted <a href="https://bsky.app/profile/jakearchibald.com/post/3m2tfbx3dhc2r">a post from Jake</a> about an <a href="https://bsky.app/profile/firefoxdevtools.bsky.social/post/3m2rmxpk74c2a">experiment Firefox were conducting</a> to garner information about what web developers wanted to see be included in Interop 2026.</p>
<p>A group effort by major browser makers: Apple, Bocoup, Google, Igalia, Microsoft and Mozilla, the <a href="https://wpt.fyi/interop-2025">Interop Project</a> (essentially) attempts to make the web work the same in every browser. Each year these companies agree on a set of web standards (created by organisations like <a href="https://whatwg.org/">WHATWG</a> and <a href="https://www.w3.org/">W3C</a>) to focus on, to test, and to implement in their respective browsers throughout the year.</p>
<p>I like this idea, it doesn’t hide itself away in a meeting room somewhere, it goes out and asks the community, it looks at what’s being written. What existing features are broken or what bugs they have. What can be improved, and what folks would love to see. Historically, for me, finding out about this has been catching a post (or repost) by a developer advocate that I’ve managed to see in my timeline.</p>
<p>This brings me back to <a href="https://bsky.app/profile/jakearchibald.com/post/3m2tfbx3dhc2r">Jakes post</a>. I opened the link and started looking at the list, it was huge, there were lots of things I thought ‘ooh, that’d be nice’ and as I scrolled down the list <a href="https://bsky.app/profile/sturobson.com/post/3m2tfuo3q4s2p">I decided to make and post a ‘Top 10’</a>, and inspired by <a href="https://matthiasott.com/notes/thats-my-rank">Matthias</a> I thought I’d quickly write a post with that list too.</p>
<p>So, here goes web platform lovers!</p>
<ol class="at-l-stack at-g-content" style="--layout-spacing: var(--space-xs);">
  <li>
    <a href="https://github.com/web-platform-tests/interop/issues/1006" target="_blank"
        rel="noopener noreferrer">CSS <code>margin-trim</code></a>
      <p>Removes the margins of child elements when they meet the edges of the container.
      </p>
  </li>
  <li>
    <a href="https://github.com/web-platform-tests/interop/issues/1103" target="_blank"
        rel="noopener noreferrer">CSS <code>@supports</code> for at-rules, nesting, and other CSS
        syntax</a>
  </li>
  <li>
    <a href="https://github.com/web-platform-tests/interop/issues/1136" target="_blank"
        rel="noopener noreferrer">CSS <code>text-wrap: pretty</code></a>
      <p>Prioritises better layout over speed when text is broken into multiple lines.</p>
  </li>
  <li>
    <a href="https://github.com/web-platform-tests/interop/issues/1165" target="_blank"
        rel="noopener noreferrer">CSS <code>contrast-color()</code> function</a>
      <p>Picks a color that has guaranteed contrast against a specified foreground or background color.</p>
  </li>
  <li>
    <a href="https://github.com/web-platform-tests/interop/issues/1032" target="_blank"
        rel="noopener noreferrer">CSS <code>@container style()</code></a>
      <p>Apply styles based on the values of custom properties of a container.</p>
  </li>
  <li>
    <a href="https://github.com/web-platform-tests/interop/issues/1043" target="_blank"
        rel="noopener noreferrer">CSS <code>hanging-punctuation</code> property</a>
      <p>Puts punctuation characters outside of the box to align the text with the rest of the document.</p>
  </li>
  <li>
    <a href="https://github.com/web-platform-tests/interop/issues/1102" target="_blank"
        rel="noopener noreferrer">CSS Gap decorations</a>
      <p><code>column-rule</code> and <code>row-rule</code> display decorative lines between columns and rows of a flex, grid, or multi-column layout.</p>
  </li>
  <li>
    <a href="https://github.com/web-platform-tests/interop/issues/1028" target="_blank"
        rel="noopener noreferrer">CSS <code>accent-color</code> property</a>
      <p>Sets a color for checkboxes, radio buttons, and other form controls.</p>
  </li>
  <li>
    <a href="https://github.com/web-platform-tests/interop/issues/1172" target="_blank"
        rel="noopener noreferrer">CSS anchor positioning</a>
      <p>Places an element based on the position of another element.</p>
  </li>
  <li>
    <a href="https://github.com/web-platform-tests/interop/issues/1083" target="_blank"
        rel="noopener noreferrer">Web Share API</a>
      <p>Invokes the device's native sharing mechanism and passes text, links, files, and other content to share targets.</p>
  </li>
</ol>
<p>As of publishing this article, there's still time to <a href="https://interop-rank.jakearchibald.com">sign-in and add your most wanted features</a> ❤️</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Un-Sass&#39;ing My CSS: Compiling Multiple CSS Files into One</title>
      <link href="https://www.alwaystwisted.com/articles/UnSassing-my-CSS-CSS-imports.html"/>
      <updated>2025-09-05T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/UnSassing-my-CSS-CSS-imports.html</id>
      <content type="html">
        <![CDATA[
        <p>As mentioned in <a href="/articles/UnSassing-my-CSS/">my last article</a>, my current client work sees me at the start of a much larger Design System project where the deliverables will be as close to vanilla HTML, CSS, and JavaScript as possible. This means we’re not using Sass, and for the first time (in a long time) I’m able to explore more of what modern CSS can do (whilst relying on browser support) instead of reaching for Sass as I normally would.</p>
<p>There are lots of things I like and love about Sass, and there’s a lot that can be done (or can soon to be done) using new CSS features. However, one thing that won’t reach CSS, and something that I think we would always need some aspect of 'tooling' for, is to compile various Sass (or CSS) files into one.</p>
<h2 id="why-compile-css%3F" tabindex="-1">Why Compile CSS?</h2>
<p>Compiling multiple CSS files into one brings several benefits. By reducing the number of CSS files, you decrease HTTP requests, which can significantly improve page load times. Additionally, maintaining a single CSS file can simplify your workflow, making it easier to manage styles across different components. Furthermore, a single, minified CSS file can enhance the performance of your website, leading to a better user experience.</p>
<p>While HTTP/2 can support multiple requests efficiently, relying solely on it and multiple imports doesn't eliminate the overhead and complexity of managing numerous files, which can still impact performance and workflow efficiency. Compiling CSS into a single file, I think, remains essential for streamlined management and consistent performance across all browsers and devices.</p>
<h2 id="tackling-css-compilation-without-sass" tabindex="-1">Tackling CSS Compilation Without Sass</h2>
<p>To achieve this without Sass, we can use tools like PostCSS or a custom script to compile our CSS files. Yes, we could write in one CSS file and depending on your project that might work, but for all of my client work it’s been best to have separate files for aspects of the code that get unified into a single CSS file that is served.</p>
<h3 id="method-1%3A-using-postcss" tabindex="-1">Method 1: Using PostCSS</h3>
<p>PostCSS is a versatile tool that transforms CSS with JavaScript plugins. This method leverages the postcss-import plugin to handle CSS imports and bundle multiple files into one. PostCSS offers a straightforward, configurable approach that integrates well with modern frontend build systems. By using PostCSS, you maintain a clean development structure with separate CSS files while automatically generating a single production file, reducing HTTP requests and improving page load performance.</p>
<h4 id="setting-up-postcss-for-compilation" tabindex="-1">Setting Up PostCSS for Compilation</h4>
<p>To compile your CSS files into one using <a href="https://postcss.org/">PostCSS</a>, follow these steps:</p>
<h4 id="step-1%3A-install-postcss-and-required-plugins" tabindex="-1">Step 1: Install PostCSS and Required Plugins</h4>
<p>First, ensure you have PostCSS installed, along with the <a href="https://github.com/postcss/postcss-import">postcss-import</a> plugin:</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> --save-dev postcss postcss-import</code></pre>
<h4 id="step-2%3A-configure-postcss" tabindex="-1">Step 2: Configure PostCSS</h4>
<p>In your PostCSS configuration file (e.g., postcss.config.js), include the postcss-import plugin:</p>
<pre class="language-javascript"><code class="language-javascript">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">plugins</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'postcss-import'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token comment">// other plugins can be added here</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>The <code>postcss-import</code> plugin automatically resolves nested imports, allowing you to have imports inside imported files while still generating a single compiled output file with the correct cascade order.</p>
</div>
<h4 id="step-3%3A-organise-your-css-files" tabindex="-1">Step 3: Organise Your CSS Files</h4>
<p>Create a overarching, global CSS file (e.g., main.css) where you will import all your other CSS files:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* main.css */</span>

<span class="token atrule"><span class="token rule">@import</span> <span class="token string">'tokens.css'</span><span class="token punctuation">;</span></span>
<span class="token atrule"><span class="token rule">@import</span> <span class="token string">'components/button.css'</span><span class="token punctuation">;</span></span>
<span class="token atrule"><span class="token rule">@import</span> <span class="token string">'components/card.css'</span><span class="token punctuation">;</span></span>
<span class="token atrule"><span class="token rule">@import</span> <span class="token string">'layouts/grid.css'</span><span class="token punctuation">;</span></span></code></pre>
<h4 id="step-4%3A-build-your-css" tabindex="-1">Step 4: Build Your CSS</h4>
<p>Run your PostCSS build process to generate a single output file:</p>
<pre class="language-bash"><code class="language-bash">postcss main.css <span class="token parameter variable">-o</span> output.css</code></pre>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>PostCSS can seamlessly integrate with popular build tools like webpack, Gulp, and Rollup, allowing you to incorporate CSS compilation into your existing development workflow without potential, additional configuration headaches.</p>
</div>
<h3 id="method-2%3A-custom-script-for-compilation" tabindex="-1">Method 2: Custom Script for Compilation</h3>
<p>If you prefer not to use PostCSS, you could instead create a Node.js script to compile your CSS.
This method uses a custom Node.js script to handle CSS compilation without additional dependencies like PostCSS. The script reads your main CSS file, processes any @import statements it finds, concatenates the contents of all imported files, and outputs a single compiled CSS file. This approach gives you complete control over the compilation process and can be tailored to specific project requirements. It's lightweight, requires minimal setup beyond Node.js itself, and can be easily integrated into your existing workflow or build process.</p>
<p><strong>Step 1: Create the Script</strong>
Create a file named compile-css.js and add the following code:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> path <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Function to read and compile CSS</span>
<span class="token keyword">function</span> <span class="token function">compileCSS</span><span class="token punctuation">(</span><span class="token parameter">inputFile<span class="token punctuation">,</span> outputFile</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> cssContent <span class="token operator">=</span> fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span>inputFile<span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> imports <span class="token operator">=</span> cssContent<span class="token punctuation">.</span><span class="token function">match</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">@import\s+['"]([^'"]+)['"]</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

  <span class="token keyword">let</span> compiledCSS <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>

  <span class="token comment">// Read and append each imported CSS file</span>
  imports<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">importStatement</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> filePath <span class="token operator">=</span> importStatement<span class="token punctuation">.</span><span class="token function">match</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">['"]([^'"]+)['"]</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> fullPath <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">dirname</span><span class="token punctuation">(</span>inputFile<span class="token punctuation">)</span><span class="token punctuation">,</span> filePath<span class="token punctuation">)</span><span class="token punctuation">;</span>
    compiledCSS <span class="token operator">+=</span> fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span>fullPath<span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">'\n'</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Write the compiled CSS to the output file</span>
  fs<span class="token punctuation">.</span><span class="token function">writeFileSync</span><span class="token punctuation">(</span>outputFile<span class="token punctuation">,</span> compiledCSS<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Compiled CSS written to </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>outputFile<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// Usage</span>
<span class="token keyword">const</span> inputCSSFile <span class="token operator">=</span> <span class="token string">'index.css'</span><span class="token punctuation">;</span> <span class="token comment">// Your main CSS file</span>
<span class="token keyword">const</span> outputCSSFile <span class="token operator">=</span> <span class="token string">'output.css'</span><span class="token punctuation">;</span> <span class="token comment">// Output file</span>

<span class="token function">compileCSS</span><span class="token punctuation">(</span>inputCSSFile<span class="token punctuation">,</span> outputCSSFile<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>With the flat file structure and single-level import strategy I employ, nested imports (you can do with <code>postcss-import</code> aren't necessary for my project setup, simplifying the compilation process while maintaining clean organisation.</p>
</div>
<p><strong>Step 2: Run the Script</strong>
Ensure you have Node.js installed, then run the script from your terminal:</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">node</span> compile-css.js</code></pre>
<p>This will read the index.css file, compile all the @imported CSS files, and create a single output.css file.</p>
<h2 id="conclusion" tabindex="-1">Conclusion</h2>
<p>Compiling multiple CSS files into one is a straightforward process, whether you choose to use PostCSS or a custom Node.js script. This approach not only improves the performance of your website but also simplifies the management of your stylesheets. By keeping your styles organised and consolidated, you can focus more on development and less on file management. As you continue to refine your CSS workflow, consider incorporating these methods to enhance your projects.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Un-Sass’ing my CSS</title>
      <link href="https://www.alwaystwisted.com/articles/UnSassing-my-CSS.html"/>
      <updated>2025-08-12T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/UnSassing-my-CSS.html</id>
      <content type="html">
        <![CDATA[
        <p>If you’ve been following me for a while, you’ll know that I’m a big fan of Sass. Whether it's writing articles, running workshops, curating the Sass News email newsletter, or serving as the tech editor for SitePoint, commissioning two fresh Sass articles each week, it’s safe to say I’ve been an enthusiastic supporter of Sass for the last fourteen years.</p>
<h2 id="however" tabindex="-1">However</h2>
<p>I’m currently assisting a client with what could be the beginning of a brand new Design System through several smaller projects. The website is somewhere between ten to fifteen years old, and the front-end team, while embedded, cannot necessarily keep pace with the advancements in modern CSS. This is largely due to the constraints of the old codebase, which make it challenging to adopt new practices and technologies.</p>
<p>Because of this, we decided to leverage ‘the platform’ as much as possible. We’re not using a preprocessor; instead, we’re relying on features that are ‘newly available’ or ‘widely available’ with Baseline, using modern CSS and almost all the toys in the box.</p>
<p>The only thing we are using is a small script that compiles all the CSS files into one larger file, following the ⁠@import order. This is because, architecturally, we are colocating a component’s CSS file with its corresponding HTML file in the same folder, but not within the same file (yuck!).</p>
<h2 id="un-sass%E2%80%99ing%3F" tabindex="-1">Un-Sass’ing?</h2>
<p>With this in mind, I thought I’d start another little series of articles. This time, I’ll be showcasing how aspects of modern CSS can replace your favourite CSS preprocessor, what I’m goint to call “Un-Sass’ing.”</p>
<h2 id="adding-transparency-to-a-colour" tabindex="-1">Adding Transparency To A Colour</h2>
<p>As we work in an agile environment, not everything is fully developed or finalised yet. One of the requirements we've encountered is the need to create transparent backgrounds. Since we are not using Sass for this project, I wondered if we could achieve similar effects using CSS.</p>
<p>In my search, I <a href="https://bsky.app/profile/sturobson.com/post/3lw5hz5aink2d">discovered the ⁠color() function</a>, and Manuel kindly shared some other <a href="https://codepen.io/matuzo/pen/EaVwEoJ?editors=0100">examples of different ways to implement transparency in using modern CSS</a>.</p>
<h3 id="the-sass-way" tabindex="-1">The Sass Way</h3>
<p>In previous projects using Sass, we could easily add transparency to colours using the <code>⁠rgba()</code> function. This function allows us to define a colour with an alpha value, which determines the level of transparency. For instance, we would typically define a colour variable at the beginning of our stylesheet, like this:</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$primary-color</span></span><span class="token punctuation">:</span> #c0ffee<span class="token punctuation">;</span>
<span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">rgba</span><span class="token punctuation">(</span><span class="token variable">$primary-color</span><span class="token punctuation">,</span> 0.4<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>By using ⁠<code>rgba()</code>, Sass interprets ⁠<code>$primary-color</code> as a colour value and allows us to specify the alpha channel without needing to break down the colour into its red, green, and blue components manually.
This approach made it straightforward to create semi-transparent backgrounds, hover effects, or overlays, enhancing the visual depth of our designs.</p>
<h3 id="the-css-way" tabindex="-1">The CSS Way</h3>
<p>Now, with modern CSS, we have a variety of options to achieve similar results without relying on a preprocessor. One effective method is using the <code>⁠color()</code> function, which allows us to define a colour based on a CSS variable and adjust its transparency.</p>
<p>According to the ~<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color">MDN Web Docs</a>~, the ⁠<code>color()</code> function enhances our ability to work with colours in CSS, making it easier to create visually appealing designs that adapt to different contexts. This flexibility allows us to maintain a streamlined workflow while achieving the desired effects, such as transparency, without the need for a preprocessor.</p>
<p>For example, we can create a transparent background using the following syntax:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-primary</span><span class="token punctuation">:</span> #bada55<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.component</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">color</span><span class="token punctuation">(</span>from <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span> srgb r g b / 0.2<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>In this example, <code>⁠var(--color-primary)</code> retrieves the primary colour defined in CSS variables, while ⁠srgb specifies the colour space. The <code>⁠r g b</code> components extract the red, green, and blue values, and the ⁠<code>/ 0.2</code> at the end sets the alpha channel for transparency, allowing us to effectively control the opacity of the colour.</p>
<h2 id="the-other-css-ways" tabindex="-1">The Other CSS Ways</h2>
<p>In addition to the <code>color()</code> function, modern CSS provides several other methods for adding transparency and manipulating colours using CSS custom properties:</p>
<h3 id="using-rgba()-directly" tabindex="-1">Using <code>rgba()</code> Directly</h3>
<p>You can use the <code>rgba()</code> function directly in CSS to define colours with transparency by referencing a custom property:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-primary</span><span class="token punctuation">:</span> #bada55<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.component</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">rgba</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span> 0.4<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="utilising-hsla()" tabindex="-1">Utilising <code>hsla()</code></h3>
<p>The <code>hsla()</code> function allows you to work with colours in the HSL colour space, providing another way to define colours with transparency using custom properties:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-primary</span><span class="token punctuation">:</span> <span class="token function">hsl</span><span class="token punctuation">(</span>91<span class="token punctuation">,</span> 52%<span class="token punctuation">,</span> 59%<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.component</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">hsla</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span> 0.4<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="mixing-with-%E2%81%A0color-mix()" tabindex="-1">Mixing with <code>⁠color-mix()</code></h3>
<p>The <code>⁠color-mix()</code> function allows you to blend a custom property with another colour, including transparency, to create a new colour effect:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-primary</span><span class="token punctuation">:</span> #bada55<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.component</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>in srgb<span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span> 20%<span class="token punctuation">,</span> transparent<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="fin" tabindex="-1">Fin</h2>
<p>I still have some trepidation about fully transitioning to CSS-only solutions. While modern CSS offers a wealth of features that can effectively replace many of the functionalities traditionally provided by Sass, I believe that making decisions on tooling should be based on a project-by-project basis. Each project has its unique requirements, and the choice between using Sass or relying solely on CSS should reflect the specific needs and goals of that project.</p>
<p>Sass still has its benefits, particularly in managing complex styles and maintaining a consistent design system. However, as the demand for modern design solutions increases, it’s evident that there is a growing array of new CSS capabilities that can handle many tasks we previously relied on Sass for.</p>
<p>This article may mark the beginning on &quot;Un-Sass’ing&quot; CSS, where I could continue to showcase how to replace favoured Sass functionality with modern CSS techniques.</p>
<p>Would you like to learn more about what and how we can replace Sass with CSS? <a href="https://bsky.app/profile/sturobson.com">Let me know</a>!</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Creating a Component for Positioning Content</title>
      <link href="https://www.alwaystwisted.com/articles/creating-a-component-for-positiong-content.html"/>
      <updated>2025-07-30T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/creating-a-component-for-positiong-content.html</id>
      <content type="html">
        <![CDATA[
        <p>For a recent client project, I’ve been helping them transform and update parts of their web presence, and one of the key updates was a brand-new home page. With initial designs to work from, I realised that one particular container could serve as a reusable component across various sections of the project.</p>
<p>This component is relatively simple in appearance—a background image with some text overlaid. In the designs I encountered, the text was primarily positioned in the ‘bottom left’ and ‘top center’ of the container. I thought it would be efficient to use ⁠place-self to easily define where the content should sit, allowing for a clean and flexible layout that can adapt to different content needs.</p>
<p>In this post, I’ll walk you through the process of creating this component, showcasing how to implement it using CSS Grid and the ⁠<code>place-self</code> property.</p>
<h3 id="component-overview" tabindex="-1">Component Overview</h3>
<p>Looking at the design I found three things that could be changeable.</p>
<h3 id="flexible-positioning%3A" tabindex="-1">Flexible Positioning:</h3>
<p>Although the current designs only had the text positioned in two places, I thought we should make it more flexible and allow the content area to be in more positions. Using <code>place-self</code> this component can offer nine distinct positioning options.</p>
<h3 id="custom-width%3A" tabindex="-1">Custom Width:</h3>
<p>Another feature I wanted to add was the ability to set a custom width for the content block (with a sensible default). Defining the width using CSS variables allows us to easily adapt the component to fit various design needs.</p>
<h3 id="surface-options%3A" tabindex="-1">Surface Options:</h3>
<p>The choice of background image would determine if the content block is more accessible and readable so I wanted to support two surface styles: light and dark. The light surface features a subtle gray background, providing contrast against darker images, while the dark surface offers a semi-transparent black background for improved visibility on lighter images.</p>
<h2 id="building-the-component-structure" tabindex="-1">Building the component structure</h2>
<p>To effectively position content on a background image, I needed to establish a clear HTML structure for the component. Essentially, I wanted a parent and child element. The parent being the horizontal slice of the web page, a section, and a child component that holds the content but defines their position, width, and colours.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>section</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>_DS-spot-content<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span>
    <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>_DS-spot-content__content<span class="token punctuation">"</span></span>
    <span class="token attr-name">data-surface</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>dark<span class="token punctuation">"</span></span>
    <span class="token attr-name">data-position</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>start start<span class="token punctuation">"</span></span>
    <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">--spot-content-width</span><span class="token punctuation">:</span> 400px<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span>
  <span class="token punctuation">></span></span>
    /* Content Goes Here */
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>section</span><span class="token punctuation">></span></span></code></pre>
<p>Now we’ve got the basics, let’s get some styling.</p>
<h2 id="styling-the-component" tabindex="-1">Styling the component</h2>
<p>To bring our component to life, we will use CSS Grid for layout management and the place-self property for precise content positioning. This approach allows us to create a flexible and responsive design that adapts seamlessly to various screen sizes.</p>
<h3 id="using-css-grid" tabindex="-1">Using CSS Grid</h3>
<p>CSS Grid is a powerful layout system that enables us to create complex grid-based layouts with ease. For our component, we can define a grid container that takes up the full height of the viewport, allowing us to position our content block anywhere within that space.
Here's how we set up the grid layout:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">._DS-spot-content</span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> 100dvh<span class="token punctuation">;</span> <span class="token comment">/* Full viewport height */</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
  <span class="token selector">> *</span> <span class="token punctuation">{</span>
    <span class="token property">grid-area</span><span class="token punctuation">:</span> 1 / 1<span class="token punctuation">;</span> <span class="token comment">/* Ensures the content block occupies the full grid area */</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="styling-with-place-self" tabindex="-1">Styling with <code>place-self</code></h4>
<p>The <code>place-self</code> property is a shorthand that combines both <code>align-self </code>and <code>justify-self</code>, allowing us to control the alignment of grid items with a single declaration. This simplifies our CSS and makes it easier to manage the positioning of content blocks.</p>
<h4 id="positioning-logic" tabindex="-1">Positioning Logic</h4>
<p>Using <code>place-self</code>, we can specify how the content block should be aligned within the grid.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">[data-position='start']</span> <span class="token punctuation">{</span>
  <span class="token property">place-self</span><span class="token punctuation">:</span> start start<span class="token punctuation">;</span> <span class="token comment">/* Aligns content to the top-left */</span>
<span class="token punctuation">}</span>
<span class="token selector">[data-position='end']</span> <span class="token punctuation">{</span>
  <span class="token property">place-self</span><span class="token punctuation">:</span> end<span class="token punctuation">;</span> <span class="token comment">/* Aligns content to the bottom-right */</span>
<span class="token punctuation">}</span>
<span class="token selector">[data-position='center']</span> <span class="token punctuation">{</span>
  <span class="token property">place-self</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span> <span class="token comment">/* Centers content both vertically and horizontally */</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Additional positioning configurations */</span>
<span class="token selector">[data-position='start start']</span> <span class="token punctuation">{</span>
  <span class="token property">place-self</span><span class="token punctuation">:</span> start start<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">[data-position='start center']</span> <span class="token punctuation">{</span>
  <span class="token property">place-self</span><span class="token punctuation">:</span> start center<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">[data-position='start end']</span> <span class="token punctuation">{</span>
  <span class="token property">place-self</span><span class="token punctuation">:</span> start end<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">[data-position='center center']</span> <span class="token punctuation">{</span>
  <span class="token property">place-self</span><span class="token punctuation">:</span> center center<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">[data-position='center start']</span> <span class="token punctuation">{</span>
  <span class="token property">place-self</span><span class="token punctuation">:</span> center start<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">[data-position='center end']</span> <span class="token punctuation">{</span>
  <span class="token property">place-self</span><span class="token punctuation">:</span> center end<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">[data-position='end start']</span> <span class="token punctuation">{</span>
  <span class="token property">place-self</span><span class="token punctuation">:</span> end start<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">[data-position='end center']</span> <span class="token punctuation">{</span>
  <span class="token property">place-self</span><span class="token punctuation">:</span> end center<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">[data-position='end end']</span> <span class="token punctuation">{</span>
  <span class="token property">place-self</span><span class="token punctuation">:</span> end end<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="defining-the-width-with-a-custom-property" tabindex="-1">Defining the width with a custom property</h3>
<p>One of the features of this component is the ability to define the width of the content block using a custom CSS property. To implement this, we use a CSS custom property, <code>—spot-content-width</code>, which can be set directly as an inline style of the HTML or defined within the CSS itself.</p>
<p>Having the custom property as an inline style could benefit implementation in a CSS, where a content creator can decide how wide this content block should be, like this:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span>
  <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>_DS-spot-content__content<span class="token punctuation">"</span></span>
  <span class="token attr-name">data-surface</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>dark<span class="token punctuation">"</span></span>
  <span class="token attr-name">data-position</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>start start<span class="token punctuation">"</span></span>
  <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">--spot-content-width</span><span class="token punctuation">:</span> 400px<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span>
<span class="token punctuation">></span></span>
  /* Content Goes Here */
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
<p>We could also set a default in the CSS, if there is no inline CSS custom property:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">._DS-spot-content__content</span> <span class="token punctuation">{</span>
  <span class="token property">max-width</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spot-content-width<span class="token punctuation">,</span> 50%<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Default width set to 50% */</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="defining-surface-styles" tabindex="-1">Defining Surface Styles</h3>
<p>As the content block will be on top of an image we need to enhance the readability and accessibility of it by defining a couple of surface/text colour styles.</p>
<p>We will support two distinct surface styles: light and dark. Each style is designed to provide an optimal contrast to the background image.</p>
<h4 id="light" tabindex="-1">Light</h4>
<p>The light option would be used when the background image is overly dark, or dark where the content is positions.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">._DS-spot-content__content[data-surface='light']</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">rgba</span><span class="token punctuation">(</span>220<span class="token punctuation">,</span> 220<span class="token punctuation">,</span> 220<span class="token punctuation">,</span> 0.5<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">color</span><span class="token punctuation">:</span> black<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="dark" tabindex="-1">Dark</h4>
<p>The dark styling option would be for the opposite, whe nthe background image is overly bright, or bright where the content is to be positioned.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">._DS-spot-content__content[data-surface='dark']</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">rgba</span><span class="token punctuation">(</span>20<span class="token punctuation">,</span> 20<span class="token punctuation">,</span> 20<span class="token punctuation">,</span> 0.3<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Semi-transparent dark gray */</span>
  <span class="token property">color</span><span class="token punctuation">:</span> white<span class="token punctuation">;</span> <span class="token comment">/* Text colour for better contrast */</span>
<span class="token punctuation">}</span></code></pre>
<p>In the HTML we set a data attribute <code>data-surface</code>:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span>
  <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>_DS-spot-content__content<span class="token punctuation">"</span></span>
  <span class="token attr-name">data-surface</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>light<span class="token punctuation">"</span></span>
  <span class="token attr-name">data-position</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>center center<span class="token punctuation">"</span></span>
<span class="token punctuation">></span></span>
  /* Content Goes Here */
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
<h2 id="example" tabindex="-1">Example</h2>
<div class="at-g-feature">
<iframe height="500" style="min-height: 300px; width: 100%;" scrolling="no" title="Always Twisted - Spot Content Component " src="https://codepen.io/sturobson/embed/QwjdqZY?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/QwjdqZY">
  Always Twisted - Spot Content Component </a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<p>We explored the process of creating a reusable component for positioning content over a background image. Using CSS Grid and the <code>⁠place-self</code> property, we achieved a flexible layout that allows for precise content placement with multiple positioning options. Additionally, we included a custom width setting and surface styles to enhance readability and adapt the component to various design needs.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 12) - Creating a Penpot Design Tokens Format with Style Dictionary</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-12.html"/>
      <updated>2025-04-11T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-12.html</id>
      <content type="html">
        <![CDATA[
        <p>In the last article, I delved into <a href="https://www.alwaystwisted.com/articles/design-tokens-in-penpot">Penpot's new Design Tokens feature</a>, a promising development that (being a very early implementation) had its share of limitations.</p>
<p>Today, in this Design Tokens Workflow tutorial, I am going to walk through creating a build script in Style Dictionary that will generate a Penpot-ready JSON file with all our design tokens.</p>
<p>In Penpot's implementation, design tokens are created and managed through a UI. The tokens can be grouped into &quot;Token Sets&quot; and &quot;Token Themes&quot;, offering a flexible hierarchical structure. You can learn more about Penpot's Design Tokens from their ~<a href="https://help.penpot.app/user-guide/design-tokens/">official documentation</a>~.</p>
<h2 id="creating-token-examples-in-json-format" tabindex="-1">Creating Token Examples in JSON Format</h2>
<p>To illustrate the process of creating Penpot-ready <code>.json</code>, let's use a few (crude) design token examples.</p>
<h3 id="core-tokens" tabindex="-1">Core Tokens</h3>
<p>We start with our core tokens, specifically our colour tokens. These tokens will be stored in a file named ⁠<code>core/01-base/color.tokens</code> to ensure they are imported first by Penpot.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"blue"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"100"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#cce4f6"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"200"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#b3d4ee"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"red"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"100"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ffe5e5"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"200"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ffcccc"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="semantic-tokens" tabindex="-1">Semantic Tokens</h3>
<p>Next, we have our semantic tokens, which will override our base tokens where required. Let's create two files for this, ⁠semantic/01-base/color.tokens.json and ⁠semantic/02-brand-a/color.tokens.json. These files will contain semantic color tokens for our base theme and a specific brand, respectively.</p>
<p>Here's an example for ⁠<code>semantic/01-brand-a/color.tokens</code>:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"default"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.blue.100.value}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"muted"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.blue.200.value}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"default"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.blue.100.value}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"hover"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.blue.200.value}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>And for <code>semantic/02-brand-b/color.tokens</code>:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"default"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.red.100.value}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"muted"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.red.200.value}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"default"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.red.100.value}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"hover"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.red.200.value}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="an-importance-for-numbering-folders" tabindex="-1">An Importance for Numbering Folders</h3>
<p>In the above examples, you can see that the folders storing our token files are prefixed with a number (01, 02). This numbering serves a vital purpose: it determines the import order in Penpot.</p>
<p>In Penpot, the order of tokens matters because of the way it implements the cascade (like <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascade/Cascade">the cascade in CSS</a>. A later token can overwrite a previous one if they have the same name. By numbering our folders, we can ensure that our tokens are imported in the correct order, thus preserving our desired cascade.</p>
<p>Furthermore, this numbering system also helps to keep our design token files organised and easy to navigate, especially in larger projects with many token files. The visual hierarchy provided by the numbering can make it easier to understand the relationships and dependencies between different tokens.</p>
<h2 id="a-note-on-penpots-propietary-.json-structure" tabindex="-1">A Note On Penpots Propietary <code>.json</code> Structure</h2>
<p>Before we proceed with configuring Style Dictionary, we should take a look at the proprietary <code>json</code> structure that Penpot uses for its tokens. This structure allows Penpot to manage token sets and themes effectively.
In Penpot, you can group design tokens into distinct sets, apply them across multiple themes, and control their cascading order. The mechanism behind this is a special structure in the JSON file that includes the ⁠<code>$themes</code> array and the ⁠<code>$metadata</code> object.</p>
<pre class="language-json"><code class="language-json"><span class="token property">"$themes"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"default"</span><span class="token punctuation">,</span>
      <span class="token property">"selectedTokenSets"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"base"</span><span class="token operator">:</span> <span class="token string">"enabled"</span><span class="token punctuation">,</span>
        <span class="token property">"default"</span><span class="token operator">:</span> <span class="token string">"enabled"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"brand a"</span><span class="token punctuation">,</span>
      <span class="token property">"selectedTokenSets"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"base"</span><span class="token operator">:</span> <span class="token string">"enabled"</span><span class="token punctuation">,</span>
        <span class="token property">"brand-a"</span><span class="token operator">:</span> <span class="token string">"enabled"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"$metadata"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"tokenSetOrder"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token string">"base"</span><span class="token punctuation">,</span>
      <span class="token string">"default"</span><span class="token punctuation">,</span>
      <span class="token string">"brand-a"</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token property">"activeThemes"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token string">"/default"</span><span class="token punctuation">,</span>
      <span class="token string">"/brand a"</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token property">"activeSets"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token string">"base"</span><span class="token punctuation">,</span>
      <span class="token string">"default"</span><span class="token punctuation">,</span>
      <span class="token string">"brand-a"</span>
    <span class="token punctuation">]</span>
<span class="token punctuation">}</span></code></pre>
<p>Let's break this structure down:</p>
<ul>
<li><code>$themes</code>: This is an array of theme objects. Each theme object must have a <code>⁠name</code> and a <code>⁠selectedTokenSets</code> object. The ⁠`selectedTokenSets object should list all token sets that are enabled for that theme.</li>
<li>⁠<code>$metadata</code>: This object contains three properties: <code>tokenSetOrder</code>, <code>⁠activeThemes</code>, and <code>⁠activeSets</code>.
<ul>
<li><code>tokenSetOrder</code>: An array that defines the order in which token sets are imported into Penpot. This is vital for controlling the cascade of tokens.</li>
<li>⁠<code>activeThemes</code>: An array that lists the themes currently active in the Penpot interface.</li>
<li>⁠<code>activeSets</code>: An array that indicates the token sets active in the Penpot interface.</li>
</ul>
</li>
</ul>
<p>This structure provides a flexible and powerful way to manage design tokens in Penpot, enabling you to maintain consistency across different themes and platforms so we need to make sure our Style Dictionary build script creates the output similar to this too.</p>
<h2 id="configuring-style-dictionary-for-penpot" tabindex="-1">Configuring Style Dictionary for Penpot</h2>
<p>To turn these design tokens into a format that Penpot can read we need to create a custom format and a helper function in Style Dictionary. Here is the complete code we need. I will break it down further next:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> fs <span class="token keyword">from</span> <span class="token string">'fs'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> path <span class="token keyword">from</span> <span class="token string">'path'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> globSync <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'glob'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token function-variable function">getThemesAndMetadata</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> coreFolders <span class="token operator">=</span> <span class="token function">globSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens/core/*'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> semanticFolders <span class="token operator">=</span> <span class="token function">globSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens/semantic/*'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> themes <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> tokenSetOrder <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

  <span class="token comment">// Include core folders in the token set order</span>
  <span class="token keyword">const</span> sortedCoreFolders <span class="token operator">=</span> coreFolders<span class="token punctuation">.</span><span class="token function">sort</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> aPrefix <span class="token operator">=</span> <span class="token function">parseInt</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> bPrefix <span class="token operator">=</span> <span class="token function">parseInt</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> aPrefix <span class="token operator">-</span> bPrefix<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  sortedCoreFolders<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">folder</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> folderName <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>folder<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\d+-</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Remove numeric prefix</span>
    tokenSetOrder<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>folderName<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Include semantic folders in the token set order and themes</span>
  <span class="token keyword">const</span> sortedSemanticFolders <span class="token operator">=</span> semanticFolders<span class="token punctuation">.</span><span class="token function">sort</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> aPrefix <span class="token operator">=</span> <span class="token function">parseInt</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> bPrefix <span class="token operator">=</span> <span class="token function">parseInt</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> aPrefix <span class="token operator">-</span> bPrefix<span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  sortedSemanticFolders<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">folder</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> folderName <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>folder<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\d+-</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Remove numeric prefix</span>
    tokenSetOrder<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>folderName<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">if</span> <span class="token punctuation">(</span>folderName <span class="token operator">!==</span> <span class="token string">'base'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      themes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">name</span><span class="token operator">:</span> folderName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">-</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">' '</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token literal-property property">selectedTokenSets</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">base</span><span class="token operator">:</span> <span class="token string">'enabled'</span><span class="token punctuation">,</span>
          <span class="token punctuation">[</span>folderName<span class="token punctuation">]</span><span class="token operator">:</span> <span class="token string">'enabled'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    themes<span class="token punctuation">,</span>
    <span class="token literal-property property">metadata</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">$metadata</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">tokenSetOrder</span><span class="token operator">:</span> tokenSetOrder<span class="token punctuation">,</span>
        <span class="token literal-property property">activeThemes</span><span class="token operator">:</span> themes<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">theme</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>theme<span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token literal-property property">activeSets</span><span class="token operator">:</span> tokenSetOrder<span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'json/penpot'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> <span class="token function-variable function">simplifyTokens</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">tokens</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
      Object<span class="token punctuation">.</span><span class="token function">entries</span><span class="token punctuation">(</span>tokens<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">[</span>key<span class="token punctuation">,</span> token<span class="token punctuation">]</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>token<span class="token punctuation">.</span>$value <span class="token operator">!==</span> <span class="token keyword">undefined</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          result<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">$value</span><span class="token operator">:</span> token<span class="token punctuation">.</span>$value<span class="token punctuation">,</span>
            <span class="token literal-property property">$type</span><span class="token operator">:</span> token<span class="token punctuation">.</span>$type<span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> token <span class="token operator">===</span> <span class="token string">'object'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          result<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">simplifyTokens</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> result<span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>

    <span class="token keyword">const</span> <span class="token punctuation">{</span> themes<span class="token punctuation">,</span> metadata <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">getThemesAndMetadata</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> semanticTokens <span class="token operator">=</span> <span class="token function">simplifyTokens</span><span class="token punctuation">(</span>dictionary<span class="token punctuation">.</span>tokens<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>
      <span class="token punctuation">{</span> <span class="token operator">...</span>semanticTokens<span class="token punctuation">,</span> <span class="token literal-property property">$themes</span><span class="token operator">:</span> themes<span class="token punctuation">,</span> <span class="token operator">...</span>metadata <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token keyword">null</span><span class="token punctuation">,</span>
      <span class="token number">2</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Find all token files matching the pattern</span>
<span class="token keyword">const</span> tokenFiles <span class="token operator">=</span> <span class="token function">globSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens/**/*.tokens'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Configure Style Dictionary instance</span>
<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">json_combined</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'penpot.json'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'json/penpot'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
            <span class="token literal-property property">nesting</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token literal-property property">global</span><span class="token operator">:</span> <span class="token string">'src/tokens/base/**/*.tokens'</span><span class="token punctuation">,</span>
              <span class="token literal-property property">semantic</span><span class="token operator">:</span> <span class="token string">'src/tokens/semantic/**/*.tokens'</span><span class="token punctuation">,</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Ensure the build directory exists</span>
<span class="token keyword">const</span> buildDir <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'build'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>fs<span class="token punctuation">.</span><span class="token function">existsSync</span><span class="token punctuation">(</span>buildDir<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  fs<span class="token punctuation">.</span><span class="token function">mkdirSync</span><span class="token punctuation">(</span>buildDir<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// Execute the build process for the json_combined platform</span>
<span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">await</span> myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="custom-format" tabindex="-1">Custom Format</h3>
<p>We register a custom format with the ⁠<code>StyleDictionary.registerFormat</code> method. This custom format, named <code>json/penpot</code>, contains an asynchronous ⁠format function that simplifies the tokens. It also uses the <code>⁠getThemesAndMetadata</code> function to generate themes and metadata. The function then combines these into a single Penpot-friendly JSON string.</p>
<pre class="language-javascript"><code class="language-javascript">StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'json/penpot'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">format</span><span class="token operator">:</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> <span class="token function-variable function">simplifyTokens</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">tokens</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
      Object<span class="token punctuation">.</span><span class="token function">entries</span><span class="token punctuation">(</span>tokens<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">[</span>key<span class="token punctuation">,</span> token<span class="token punctuation">]</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>token<span class="token punctuation">.</span>$value <span class="token operator">!==</span> <span class="token keyword">undefined</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          result<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">$value</span><span class="token operator">:</span> token<span class="token punctuation">.</span>$value<span class="token punctuation">,</span>
            <span class="token literal-property property">$type</span><span class="token operator">:</span> token<span class="token punctuation">.</span>$type<span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> token <span class="token operator">===</span> <span class="token string">'object'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          result<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">simplifyTokens</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> result<span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>

    <span class="token keyword">const</span> <span class="token punctuation">{</span> themes<span class="token punctuation">,</span> metadata <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">getThemesAndMetadata</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> semanticTokens <span class="token operator">=</span> <span class="token function">simplifyTokens</span><span class="token punctuation">(</span>dictionary<span class="token punctuation">.</span>tokens<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>
      <span class="token punctuation">{</span> <span class="token operator">...</span>semanticTokens<span class="token punctuation">,</span> <span class="token literal-property property">$themes</span><span class="token operator">:</span> themes<span class="token punctuation">,</span> <span class="token operator">...</span>metadata <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token keyword">null</span><span class="token punctuation">,</span>
      <span class="token number">2</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="helper-function" tabindex="-1">Helper Function</h3>
<p>The <code>⁠getThemesAndMetadata</code> function is a (rather large) helper function that retrieves the sorted list of core and semantic token directories, generates themes for each semantic directory (except 'base'), and sets the order of token sets import for Penpot.</p>
<ol>
<li>Getting the List of Folders
The function begins by retrieving a list of all core and semantic token directories.</li>
</ol>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> coreFolders <span class="token operator">=</span> <span class="token function">globSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens/core/*'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> semanticFolders <span class="token operator">=</span> <span class="token function">globSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens/semantic/*'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<ol start="2">
<li>Initialising the Themes and Token Sets
The <code>⁠themes</code> and ⁠<code>tokenSetOrder</code> arrays are initialised. They will store the themes and the order of token sets for Penpot.</li>
</ol>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> themes <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> tokenSetOrder <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span></code></pre>
<ol start="3">
<li>Sorting and Processing Core Folders
The core folders are sorted numerically based on their prefixes and added to the ⁠<code>tokenSetOrder</code> array.</li>
</ol>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> sortedCoreFolders <span class="token operator">=</span> coreFolders<span class="token punctuation">.</span><span class="token function">sort</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> aPrefix <span class="token operator">=</span> <span class="token function">parseInt</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">.</span>split<span class="token punctuation">[</span><span class="token string">'-'</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token number">0</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> bPrefix <span class="token operator">=</span> <span class="token function">parseInt</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span><span class="token punctuation">.</span>split<span class="token punctuation">[</span><span class="token string">'-'</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token number">0</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> aPrefix <span class="token operator">-</span> bPrefix<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

sortedCoreFolders<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">folder</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> folderName <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>folder<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\d+-</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Remove numeric prefix</span>
  tokenSetOrder<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>folderName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<ol start="4">
<li>Sorting and Processing Semantic Folders
The semantic folders are also sorted numerically based on their prefixes. The folder names are added to the ⁠<code>tokenSetOrder</code> array. If a folder name is not 'base', a theme is created for it and added to the <code>⁠themes</code> array.</li>
</ol>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> sortedSemanticFolders <span class="token operator">=</span> semanticFolders<span class="token punctuation">.</span><span class="token function">sort</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> aPrefix <span class="token operator">=</span> <span class="token function">parseInt</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">.</span>split<span class="token punctuation">[</span><span class="token string">'-'</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token number">0</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> bPrefix <span class="token operator">=</span> <span class="token function">parseInt</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span><span class="token punctuation">.</span>split<span class="token punctuation">[</span><span class="token string">'-'</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token number">0</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> aPrefix <span class="token operator">-</span> bPrefix<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

sortedSemanticFolders<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">folder</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> folderName <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>folder<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\d+-</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Remove numeric prefix</span>
  tokenSetOrder<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>folderName<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">if</span> <span class="token punctuation">(</span>folderName <span class="token operator">!==</span> <span class="token string">'base'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    themes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      <span class="token literal-property property">name</span><span class="token operator">:</span> folderName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">-</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">' '</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
      <span class="token literal-property property">selectedTokenSets</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">base</span><span class="token operator">:</span> <span class="token string">'enabled'</span><span class="token punctuation">,</span>
        <span class="token punctuation">[</span>folderName<span class="token punctuation">]</span><span class="token operator">:</span> <span class="token string">'enabled'</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<ol start="5">
<li>Returning Themes and Metadata
Finally, the function returns an object containing the ⁠<code>themes</code> and <code>⁠metadata</code> for Penpot.</li>
</ol>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">return</span> <span class="token punctuation">{</span>
  themes<span class="token punctuation">,</span>
  <span class="token literal-property property">metadata</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">$metadata</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">tokenSetOrder</span><span class="token operator">:</span> tokenSetOrder<span class="token punctuation">,</span>
      <span class="token literal-property property">activeThemes</span><span class="token operator">:</span> themes<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">theme</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>theme<span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">,</span>
      <span class="token literal-property property">activeSets</span><span class="token operator">:</span> tokenSetOrder<span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h3 id="style-dictionary-configuration" tabindex="-1">Style Dictionary Configuration</h3>
<p>We configure Style Dictionary to use the custom format for building the tokens. The token files are sourced from the 'src/tokens' directory. The output is a 'penpot.json' file built in the 'build' directory using our 'json/dtcg' custom format.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">json_combined</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'penpot.json'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'json/dtcg'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
            <span class="token literal-property property">nesting</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token literal-property property">global</span><span class="token operator">:</span> <span class="token string">'src/tokens/base/**/*.tokens'</span><span class="token punctuation">,</span>
              <span class="token literal-property property">semantic</span><span class="token operator">:</span> <span class="token string">'src/tokens/semantic/**/*.tokens'</span><span class="token punctuation">,</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="build-execution" tabindex="-1">Build Execution</h3>
<p>Finally, we ensure the build directory exists, and then run the build process for the ⁠<code>json_combined</code> platform, which generates our Penpot-ready design tokens file.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> buildDir <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'build'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>fs<span class="token punctuation">.</span><span class="token function">existsSync</span><span class="token punctuation">(</span>buildDir<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  fs<span class="token punctuation">.</span><span class="token function">mkdirSync</span><span class="token punctuation">(</span>buildDir<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">await</span> myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="the-penpot-ready-.json-generated-example" tabindex="-1">The Penpot-ready <code>.json</code> Generated Example</h2>
<p>After running the build script, we should have a <code>⁠penpot.json</code> file in our ⁠build directory with all our design tokens. The output should look similar to this:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"blue"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"100"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#cce4f6"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"200"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#b3d4ee"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"red"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"100"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ffe5e5"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"200"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ffcccc"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"default"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.blue.100.value}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"muted"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.blue.200.value}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"default"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.blue.100.value}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"hover"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.blue.200.value}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"$themes"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"default"</span><span class="token punctuation">,</span>
      <span class="token property">"selectedTokenSets"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"base"</span><span class="token operator">:</span> <span class="token string">"enabled"</span><span class="token punctuation">,</span>
        <span class="token property">"default"</span><span class="token operator">:</span> <span class="token string">"enabled"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"brand a"</span><span class="token punctuation">,</span>
      <span class="token property">"selectedTokenSets"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"base"</span><span class="token operator">:</span> <span class="token string">"enabled"</span><span class="token punctuation">,</span>
        <span class="token property">"brand-a"</span><span class="token operator">:</span> <span class="token string">"enabled"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token property">"$metadata"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"tokenSetOrder"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"base"</span><span class="token punctuation">,</span> <span class="token string">"default"</span><span class="token punctuation">,</span> <span class="token string">"brand-a"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token property">"activeThemes"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"/default"</span><span class="token punctuation">,</span> <span class="token string">"/brand a"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token property">"activeSets"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"base"</span><span class="token punctuation">,</span> <span class="token string">"default"</span><span class="token punctuation">,</span> <span class="token string">"brand-a"</span><span class="token punctuation">]</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="wrapping-up" tabindex="-1">Wrapping Up</h2>
<p>I’ve walked through how to create a build script using Style Dictionary to generate a Penpot-ready <code>.json</code> file with all your existing design tokens. This is helpful if your ‘source of truth’ for your Design Tokens is somewhere else and Penpot is one more destination for their use. The complete code and examples for this article can be found in the <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/12-exporting-to-penpot">GitHub repository</a>.</p>
<p>As a front-end developer and a Design Systems consultant I feel I’m in a perpetual pendulum of where I think your design tokens source of truth should live. However, like most things, it kind of depends on your team, your products and your workflows. This is an option if you’re design tokens are in code, or if you’re moving towards Penpot as your design tool.</p>
<p>Regardless of where you are on your design systems journey, remember: keep iterating, keep improving, and keep exploring the tools at your disposal, just like I have done with Penpot.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Tokens have landed in Penpot, kinda</title>
      <link href="https://www.alwaystwisted.com/articles/design-tokens-in-penpot.html"/>
      <updated>2025-04-10T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-tokens-in-penpot.html</id>
      <content type="html">
        <![CDATA[
        <p>At the end of last week I found myself spending the day at my partners antiques centre whilst they were away. It was quiet, not so many PPPs (pick up, put down, p*ss off) but a few SSSs (small significant sales).</p>
<p>I found myself sat on an old upholstered chair with my laptop and thought I’d have a go at creating a ‘design tokens starter’ for <a href="https://penpot.app">Penpot</a>.</p>
<p>After working out how to create circles and text, group them, duplicate them and group them again I was already tired at how much work was involved (“this would be easier in code” I said to my-(front-end-developer)-self).</p>
<p>I then spotted it, the Design Tokens panel and shifted gears.</p>
<p><img src="/images/articles/penpot/tokens-panel.jpg" alt="the design tokens panel UI for Penpot" loading="lazy" decoding="async"></p>
<p>Nice, a way to create design tokens built into the UI, including themes, sets and the tokens themselves.</p>
<p>I clicked the little plus icon next to <code>border-radius</code> and was given a popup to add a new token.</p>
<p><img src="/images/articles/penpot/border-radius.jpg" alt="the design tokens panel UI for Penpot with a popup next to is with form fields for a new token - name, value, description" loading="lazy" decoding="async"></p>
<p>Adding a new theme also had a similar pop up:</p>
<p><img src="/images/articles/penpot/new-theme.jpg" alt="a 'add new layer' popup with fields for group and theme" loading="lazy" decoding="async"></p>
<p>Adding a new set gave me something a little different:</p>
<p><img src="/images/articles/penpot/new-set.jpg" alt="the design tokens panel UI with a form input for a new set name" loading="lazy" decoding="async"></p>
<p>At the bottom of this side panel had another button that was labelled ‘tools’. I clicked it, who doesn’t click a new button.</p>
<p><img src="/images/articles/penpot/export.jpg" alt="a popup containing two items - import and export above a button titled 'tools'" loading="lazy" decoding="async"></p>
<p>Ooh, an “import” and an “export” option. “Ok, let’s look for some documentation on this.” I thought and went to my favourite browser of choice and started searcing.</p>
<h2 id="to-the-documentation!" tabindex="-1">To The Documentation!</h2>
<p>I found <a href="https://help.penpot.app/user-guide/design-tokens/">documentation explaining this panel</a> (and a bit more) on their site.</p>
<p>It’s using the <a href="https://tr.designtokens.org/format/">W3C Design Tokens Community Group Draft Format</a>, it shows how you can reference tokens, what tokens you can create, edit, and use. It also introduces “Token Sets” (<a href="https://designtokens.fyi/#/terms/tier/">layers, or teirs</a> pehaps) and “Token Themes”.</p>
<h3 id="tokens" tabindex="-1">Tokens</h3>
<p>Creating a token using the UI allows you to add:</p>
<ul>
<li><strong>name:</strong> what you are naming the token (unsurprisingly). Be it <code>spacing.100</code> or <code>page.background.color</code> etc.</li>
<li><strong>value:</strong> depening on what type of token you’re creating you can apply a number or something from the available colour spaces (Hex, RGB, RGBA, ARGB, HSL or HSLA).</li>
<li><strong>description:</strong> the ability to add something meaningful to what the token does, is, or it’s intention.</li>
</ul>
<p>The available tokens (so far) are:</p>
<ul>
<li>color</li>
<li>dimensions</li>
<li>sizing</li>
<li>spacing</li>
<li>border radius</li>
<li>opacity</li>
<li>rotation</li>
</ul>
<p>(sadly, at the time of writing this, anything for typography seems to be missing. This new Design Tokens implementation is <em>brand new</em> so I hope we will see something coming soon).
As this implementation is making use of the specification you can also reference other tokens:</p>
<p><img src="/images/articles/penpot/reference-token.jpg" alt="the new token popup that shows how it is possible to reference an existing token in a new token" loading="lazy" decoding="async"></p>
<h3 id="token-sets" tabindex="-1">Token Sets</h3>
<p>This option gives you the ability to have defined layers (teirs) of your Design Tokens. So you can group related tokens into an easy ‘turn off and on-able’ set. You can also group token sets into a visual ‘folder’ in the UI:</p>
<p><img src="/images/articles/penpot/sets.jpg" alt="a sort of folder strucutre of token sets with global and modes, modes has light and dark nested" loading="lazy" decoding="async"></p>
<h3 id="token-themes" tabindex="-1">Token Themes</h3>
<p>Themes allow you to group your token sets for a specific context, like a unique brand or theme. Again you can also group your themes like you can with token sets. You can also apply the same token sets to multiple themes - which would be great for a multi-brand system that has similar base layer tokens. You can define all of this in the edit theme popup:</p>
<p><img src="/images/articles/penpot/edit-theme.jpg" alt="the themes popup showing what active sets are selected" loading="lazy" decoding="async"></p>
<h3 id="creating-a-quick-example" tabindex="-1">Creating a quick example</h3>
<p>I quickly popped in some tokens, added some themes and sets and came to a UI panel like this:</p>
<p><img src="/images/articles/penpot/tokens.jpg" alt="an example of the Penpot UI for Design Tokens showing a theme selected, the token sets that are active and some groups of design tokens underneath" loading="lazy" decoding="async"></p>
<p>We have ‘brand-a’ as the active theme, we have the global and both mode token sets active and we seeing the tokens that are part of the global set at the bottom of the UI.</p>
<h2 id="but%2C-as-a-developer%E2%80%A6" tabindex="-1">But, as a developer…</h2>
<p>This all looked pretty cool, as a front-end developer I wanted to know more about the importing and exporting of data.
As I’d already created a few tokens in the app, the best way to see how you can import a <code>.json</code> file was to export what I had.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"global"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"red"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#f44336"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">""</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"500"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ffcdd2"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">""</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"radius"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"100"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"2px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"borderRadius"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"2px border rarius"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"200"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"4px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"borderRadius"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"4px border rarius"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"300"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"8px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"borderRadius"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"8px border rarius"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"16px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"borderRadius"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"16px border rarius"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"blue"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#2196f3"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">""</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"900"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#0d47a1"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">""</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"mode/light"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#000000"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">""</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"mode/dark"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#FFFFFF"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">""</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"$themes"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"brand-a"</span><span class="token punctuation">,</span>
      <span class="token property">"group"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
      <span class="token property">"is-source"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
      <span class="token property">"id"</span><span class="token operator">:</span> <span class="token string">"61d2de80-46cc-80e4-8006-030e7ccd5f46"</span><span class="token punctuation">,</span>
      <span class="token property">"modified-at"</span><span class="token operator">:</span> <span class="token string">"2025-04-10T11:39:46.156+01:00"</span><span class="token punctuation">,</span>
      <span class="token property">"selectedTokenSets"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"mode/light"</span><span class="token operator">:</span> <span class="token string">"enabled"</span><span class="token punctuation">,</span>
        <span class="token property">"mode/dark"</span><span class="token operator">:</span> <span class="token string">"enabled"</span><span class="token punctuation">,</span>
        <span class="token property">"global"</span><span class="token operator">:</span> <span class="token string">"enabled"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"brand-b"</span><span class="token punctuation">,</span>
      <span class="token property">"group"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
      <span class="token property">"is-source"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
      <span class="token property">"id"</span><span class="token operator">:</span> <span class="token string">"61d2de80-46cc-80e4-8006-031314d7f8c6"</span><span class="token punctuation">,</span>
      <span class="token property">"modified-at"</span><span class="token operator">:</span> <span class="token string">"2025-04-10T11:39:52.621+01:00"</span><span class="token punctuation">,</span>
      <span class="token property">"selectedTokenSets"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"mode/light"</span><span class="token operator">:</span> <span class="token string">"enabled"</span><span class="token punctuation">,</span>
        <span class="token property">"mode/dark"</span><span class="token operator">:</span> <span class="token string">"enabled"</span><span class="token punctuation">,</span>
        <span class="token property">"global"</span><span class="token operator">:</span> <span class="token string">"enabled"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token property">"$metadata"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"tokenSetOrder"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"global"</span><span class="token punctuation">,</span> <span class="token string">"mode/light"</span><span class="token punctuation">,</span> <span class="token string">"mode/dark"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token property">"activeThemes"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"/brand-a"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token property">"activeSets"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"mode/light"</span><span class="token punctuation">,</span> <span class="token string">"mode/dark"</span><span class="token punctuation">,</span> <span class="token string">"global"</span><span class="token punctuation">]</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>So we get the code interpretation of the tokens I added, following the DTCGs specification using <code>$value</code>, <code>$type</code>, and <code>$description</code> and we also get some other information.</p>
<pre class="language-json"><code class="language-json"> <span class="token property">"$themes"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
            <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"brand-a"</span><span class="token punctuation">,</span>
            <span class="token property">"group"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
            <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
            <span class="token property">"is-source"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
            <span class="token property">"id"</span><span class="token operator">:</span> <span class="token string">"61d2de80-46cc-80e4-8006-030e7ccd5f46"</span><span class="token punctuation">,</span>
            <span class="token property">"modified-at"</span><span class="token operator">:</span> <span class="token string">"2025-04-10T11:39:46.156+01:00"</span><span class="token punctuation">,</span>
            <span class="token property">"selectedTokenSets"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
                <span class="token property">"mode/light"</span><span class="token operator">:</span> <span class="token string">"enabled"</span><span class="token punctuation">,</span>
                <span class="token property">"mode/dark"</span><span class="token operator">:</span> <span class="token string">"enabled"</span><span class="token punctuation">,</span>
                <span class="token property">"global"</span><span class="token operator">:</span> <span class="token string">"enabled"</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
            <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"brand-b"</span><span class="token punctuation">,</span>
            <span class="token property">"group"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
            <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
            <span class="token property">"is-source"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
            <span class="token property">"id"</span><span class="token operator">:</span> <span class="token string">"61d2de80-46cc-80e4-8006-031314d7f8c6"</span><span class="token punctuation">,</span>
            <span class="token property">"modified-at"</span><span class="token operator">:</span> <span class="token string">"2025-04-10T11:39:52.621+01:00"</span><span class="token punctuation">,</span>
            <span class="token property">"selectedTokenSets"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
                <span class="token property">"mode/light"</span><span class="token operator">:</span> <span class="token string">"enabled"</span><span class="token punctuation">,</span>
                <span class="token property">"mode/dark"</span><span class="token operator">:</span> <span class="token string">"enabled"</span><span class="token punctuation">,</span>
                <span class="token property">"global"</span><span class="token operator">:</span> <span class="token string">"enabled"</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token property">"$metadata"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"tokenSetOrder"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
            <span class="token string">"global"</span><span class="token punctuation">,</span>
            <span class="token string">"mode/light"</span><span class="token punctuation">,</span>
            <span class="token string">"mode/dark"</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token property">"activeThemes"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
            <span class="token string">"/brand-a"</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token property">"activeSets"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
            <span class="token string">"mode/light"</span><span class="token punctuation">,</span>
            <span class="token string">"mode/dark"</span><span class="token punctuation">,</span>
            <span class="token string">"global"</span>
        <span class="token punctuation">]</span>
    <span class="token punctuation">}</span></code></pre>
<p>The themes seem to have some propietary <code>.json</code> for the application, but it shows us:</p>
<ul>
<li>What themes are available</li>
<li>What Token Sets each theme uses</li>
</ul>
<p>Below the themes we also get some more propietary <code>.json</code>. This <code>$metadata</code> looks like it helps the Penpot UI turn on (or off) whatever token theme and it’s token sets are active.</p>
<h2 id="a-quick-wrap-up%2C-before-part-two" tabindex="-1">A Quick Wrap Up, Before Part Two</h2>
<p>Penpot’s Design Tokens implementation marks a promising but (at the moment) incomplete step forward. While the tool now supports W3C DTCG-compliant tokens – enabling themes, token sets, and cross-referencing – gaps remain.</p>
<p>The absence of typography tokens (font families, weights, line heights) undermines its utility for holistic design systems (but this feature is a week old, let’s give it some time).</p>
<p>Creating tokens manually in the UI also feels laborious (to me) compared to code-driven workflows, and proprietary metadata fields like ⁠<code>$themes</code> can risk vendor lock-in.</p>
<p>In “Part Two”, I will look at using Style Dictionary to generate a format that Penpot can use and (hopefully) see how we could use Penpots exported .json as a source of truth too (if needed).</p>
<p>I’m still in two minds at where I see Design Tokens (as a thing) being stored as a source of truth. The pendulum swings from code or design to it’s own place that design and code tools should import (but I guess that might be a article in itself).</p>
<h2 id="an-update" tabindex="-1">An update</h2>
<p>A day or two after publishing this, Xaviju reached out to update me on some of the points that I mentioend in the wrap up.</p>
<ol>
<li>They are &quot;already working on composite tokens and typography is a top priority&quot;</li>
<li>&quot;A code editor is on our roadmap&quot; 👀</li>
<li>They &quot;are working to improve the current DTCG standard with themes&quot; so the metadata could be improved to &quot; provide a better experience&quot;</li>
</ol>
<p>I also noticed that, with Laura, Penpot have released <a href="https://youtu.be/f7wQXksN_kk?si=bFrSrm8rZRtz7e2P">a short video on using Design Tokens with Penpot</a>.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 11) - Creating Sass-backed CSS Custom Properties With Style Dictionary</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-11.html"/>
      <updated>2025-04-09T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-11.html</id>
      <content type="html">
        <![CDATA[
        <p>Whilst writing my recent article on <a href="https://www.alwaystwisted.com/articles/css-vs-sass">where and when I choose to use Sass variables or CSS Custom Properties</a> in a project I thought to myself <a href="https://bsky.app/profile/did:plc:mnut7bswvnl54dhflb4qofss/post/3lmcbuowvoc2p">“you could automate this bit using style dictionary”</a>. As that article is published I’ve quickly opened up a new markdown file to write this.
In this tutorial we will look at how we can use our design tokens to not only generate Sass variables, but generate CSS custom properties that will make use of the Sass variables using interpolation.</p>
<h2 id="implementing-spacing-tokens" tabindex="-1">Implementing Spacing Tokens</h2>
<p>Let's create a sample token structure that combines scale definitions with component-specific applications.
<strong>tokens/base/spacing.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"100"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"0.125rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"spacing"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"200"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"0.25rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"spacing"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"300"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"0.5rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"spacing"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"spacing"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"800"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"2rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"spacing"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/semantic/spacing.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"component"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"margin"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"inline"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{spacing.400.$value}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"spacing"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"block"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{spacing.400.$value}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"spacing"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"padding"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"inline"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{spacing.100.$value}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"spacing"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"block"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{spacing.100.$value}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"spacing"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="style-dictionary-configuration" tabindex="-1">Style Dictionary Configuration</h2>
<p>Next we need to create a new build script that will use Style Dictionary. What we want to do is:</p>
<ul>
<li>generate a <code>.scss</code> file of the base spacing tokens as Sass variables</li>
<li>generate a <code>.scss</code> file of the semantic spacing tokens that will create a set of CSS custom properties that use Sass variables via interpolations (<code>—component-margin-inline: #{$spacing-400];</code>.</li>
</ul>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> globSync <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'glob'</span><span class="token punctuation">;</span> <span class="token comment">// For file pattern matching</span>
<span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token comment">// Find all token files matching the pattern</span>
<span class="token keyword">const</span> tokenFiles <span class="token operator">=</span> <span class="token function">globSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens/**/*.tokens'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Header comment for generated files</span>
<span class="token keyword">const</span> <span class="token constant">HEADER_COMMENT</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">// Do not edit directly, this file was auto-generated.\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

<span class="token comment">// Configure Style Dictionary instance</span>
<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">sass_base</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'scss'</span><span class="token punctuation">,</span> <span class="token comment">// Use standard SCSS transforms</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/sass/base/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'_base-tokens.scss'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'scss/variables'</span><span class="token punctuation">,</span> <span class="token comment">// SCSS variables format</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'base'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// Only process base tokens</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">css_semantic</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'scss'</span><span class="token punctuation">,</span> <span class="token comment">// Use SCSS transforms</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/sass/semantic/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'variables.scss'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/sass-ref'</span><span class="token punctuation">,</span> <span class="token comment">// Custom format defined in hooks</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// Only process semantic tokens</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token comment">// Custom format definitions</span>
  <span class="token literal-property property">hooks</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">formats</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token comment">// Custom CSS format that references Sass variables</span>
      <span class="token string-property property">'css/sass-ref'</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// Process all tokens in the dictionary</span>
        <span class="token keyword">const</span> tokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens
          <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
            <span class="token keyword">const</span> isReference <span class="token operator">=</span>
              <span class="token keyword">typeof</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$value <span class="token operator">===</span> <span class="token string">'string'</span> <span class="token operator">&amp;&amp;</span>
              token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$value<span class="token punctuation">.</span><span class="token function">startsWith</span><span class="token punctuation">(</span><span class="token string">'{'</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span>
              token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$value<span class="token punctuation">.</span><span class="token function">endsWith</span><span class="token punctuation">(</span><span class="token string">'}'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token keyword">const</span> sassVariable <span class="token operator">=</span> isReference
              <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">$</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$value
                  <span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">// Remove curly braces</span>
                  <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.\$value</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span> <span class="token comment">// Remove .$value suffix first</span>
                  <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span> <span class="token comment">// Then convert remaining dots to hyphens</span>
              <span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">$</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

            <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: #{</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>sassVariable<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">};</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
          <span class="token punctuation">}</span><span class="token punctuation">)</span>
          <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// Combine header, Sass import, and CSS variables</span>
        <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">HEADER_COMMENT</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">@use "../base/_base-tokens.scss";\n\n:root {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>tokens<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n}</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Execute the build process for all platforms</span>
myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="key-script-components" tabindex="-1">Key Script Components</h3>
<ul>
<li><strong>Token Aggregation:</strong> Using <code>⁠globSync</code> to recursively collect all ⁠<code>.token</code>s<code> files from ⁠</code>src/tokens/*<em>/</em>.tokens`.</li>
<li><strong>Smart Reference Handling:</strong> The custom <code>⁠css/sass-ref</code> format automatically:
<ul>
<li>Detects any token reference format (⁠<code>{type.path.to.token}</code>)</li>
<li>Converts dot-notation paths to Sass-friendly hyphens</li>
<li>Removes <code>⁠. $value</code> suffixes while maintaining reference integrity</li>
</ul>
</li>
<li><strong>Separation of Concerns:</strong> Platform configuration keeps base tokens (design primitives) separate from semantic tokens (contextual applications)</li>
</ul>
<p>The code for this example can be <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/11-sass-backed-css-variables">found on this branch</a> of the repo this series has been using</p>
<h2 id="generated-output-structure" tabindex="-1">Generated Output Structure</h2>
<p>The script produces two critical files. These files are:</p>
<ul>
<li>a Sass variables file that maintains design system constants.</li>
<li>a CSS custom properties file that references Sass values via interpolation.</li>
</ul>
<h3 id="base-tokens-(sass)" tabindex="-1">Base Tokens (Sass)</h3>
<p><strong>_base-tokens.scss</strong></p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$spacing-100</span></span><span class="token punctuation">:</span> 0.125rem<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-200</span></span><span class="token punctuation">:</span> 0.25rem<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-300</span></span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-400</span></span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-800</span></span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span></code></pre>
<h3 id="semantic-tokens-(css)" tabindex="-1">Semantic Tokens (CSS)</h3>
<p><strong>_variables.scss</strong></p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@use</span> <span class="token string">'../base/_base-tokens.scss'</span><span class="token punctuation">;</span>

<span class="token selector">:root </span><span class="token punctuation">{</span>
  <span class="token property">--component-margin-inline</span><span class="token punctuation">:</span> <span class="token variable">#{$spacing-400}</span><span class="token punctuation">;</span>
  <span class="token property">--component-margin-block</span><span class="token punctuation">:</span> <span class="token variable">#{$spacing-400}</span><span class="token punctuation">;</span>
  <span class="token property">--component-padding-inline</span><span class="token punctuation">:</span> <span class="token variable">#{$spacing-100}</span><span class="token punctuation">;</span>
  <span class="token property">--component-padding-block</span><span class="token punctuation">:</span> <span class="token variable">#{$spacing-100}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This Style Dictionary configuration helps solve several challenges in modern design systems:</p>
<ol>
<li><strong>Single Source of Truth</strong>: Token updates propagate through both Sass and CSS layers.</li>
<li><strong>Contextual Adaptation</strong>: Component-specific overrides maintain design consistency</li>
<li><strong>Toolchain Integration</strong>: Automates the Sass to CSS bridge while preserving both paradigms.</li>
<li><strong>Scale Maintenance</strong>: Spacing ratios remain consistent across primitive and semantic layers.</li>
</ol>
<p>By combining Style Dictionary's transformation power with Sass's preprocessing capabilities, we can create a future-proof system that works seamlessly with CSS-in-JS solutions, traditional Sass projects, and modern CSS-only architectures and more.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>CSS Custom Properties vs. Sass Variables: A Pragmatic Guide</title>
      <link href="https://www.alwaystwisted.com/articles/css-vs-sass.html"/>
      <updated>2025-04-08T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/css-vs-sass.html</id>
      <content type="html">
        <![CDATA[
        <p>In recent articles I’ve demonstrated how we can use Design Tokens to assist with theming, be it for a <a href="">multi-brand</a> Design System or a single property that has <a href="">multiple themes</a>.<br>
If you noticed, for the multi-brand configuration we were also generating Sass variables, but it in the second article on creating multiple themes for a single site we weren’t.
I have reasons for that, as part of a strategy of when and how I use CSS custom properites or Sass variables that I’ve been implementing and refining over the last 7/8 years. I thought it would make a nice little article, so here goes.</p>
<h2 id="sass-variables%2C-css-custom-properties%2C-what%E2%80%99s-the-difference%3F" tabindex="-1">Sass Variables, CSS Custom Properties, What’s the Difference?</h2>
<p>CSS custom properties and Sass variables can seem interchangeable at first glance, but I think they excel when we look at their diverging strengths:</p>
<ul>
<li><strong>Sass variables</strong> act as <strong>compile-time constants</strong>, perfect for immutable brand guidelines and mathematical foundations.</li>
<li><strong>CSS custom properties</strong> serve as <strong>runtime-adjustable variables</strong>, enabling live theming, CMS overrides, and user-facing customisation.
I think this dichotomy shows part of modern web development’s dual demands: rigid design system governance paired with flexible contextual adaptation.
Whether you’re building a WordPress theme that content editors can tweak or an SaaS platform requiring dark mode, understanding this split can help unlock smarter architectural decisions.</li>
</ul>
<h2 id="when-i-use-css-custom-properties" tabindex="-1">When I Use CSS Custom Properties</h2>
<p>CSS custom properties are indispensable when dealing with values that can or need to adapt after the page loads. Their inherent runtime flexibility can help solve specific problems static preprocessor variables just cannot touch.</p>
<h3 id="dynamic-scenarios" tabindex="-1">Dynamic Scenarios</h3>
<h4 id="browser-runtime-changes" tabindex="-1">Browser runtime changes</h4>
<p>If you have things that can update the page live without requiring a page refresh - use CSS custom properties. Great when toggling light/dark mode or changing the overtall theme.</p>
<h4 id="user-interaction" tabindex="-1">User interaction</h4>
<p>Perhaps you have some UI the user can change that effects part of the page. Changing the value of the custom property feels cleaner, and more intuitive.</p>
<h4 id="cms%2Fback-end-control" tabindex="-1">CMS/Back-End control</h4>
<p>Have you got variants or things that you’re wanting the content creators of your site to change but don’t want to add a load of classnames or restrict the variants too much. Choose the value and create the custom property on the back-end that gets used in the browser.</p>
<h4 id="media-query-overrides" tabindex="-1">Media query overrides</h4>
<p>Simplify responsive logic. Instead of redeclaring margins at breakpoints using CSS custom properties can <a href="https://www.smashingmagazine.com/2018/05/css-custom-properties-strategy-guide/">create cleaner, more logical code</a>.</p>
<h3 id="design-system-use-cases" tabindex="-1">Design System Use Cases</h3>
<h4 id="theme-variables" tabindex="-1">Theme variables</h4>
<p>Maintain consistency while permitting exceptions. <code>--color-background: var(⁠--color-background-primary);</code> ensures brand alignment, but individual components can locally override it via <code>⁠:where(.alert) { --color-background: var(--color-background-warning; }</code> without side effects.</p>
<h4 id="runtime-computations" tabindex="-1">Runtime computations</h4>
<p>Create relationships between values. <code>⁠--icon-size: calc(var(--font-size) * 1.2);</code> could keep icons proportionally sized to text, even when users adjust font scaling.</p>
<h4 id="component-level-overrides" tabindex="-1">Component-level overrides</h4>
<p>Enable safer customisation. A ⁠card component uses ⁠<code>—card-shadow</code> internally, allowing specific instances to deviate from the global shadow system without Frankenstein CSS (<code>⁠.card--special { box-shadow: ... }</code>).</p>
<h2 id="when-i-use-sass-variables" tabindex="-1">When I Use Sass Variables</h2>
<h3 id="immutable-foundations" tabindex="-1">Immutable Foundations</h3>
<h4 id="brand-enforcement" tabindex="-1">Brand Enforcement</h4>
<p>Sass variables can help lock down design decisions that should never bend. That signature brand blue isn't just a colour – it's <code>⁠$brand-blue: #2e5eaa;</code> screaming &quot;this stays put&quot; through all of the components and layout templates being used.</p>
<h4 id="precision-math-systems" tabindex="-1">Precision Math Systems</h4>
<p>Spacing scales become architectural blueprints with Sass's compile-time calculations. While CSS variables futz with <code>⁠calc()</code> at runtime, Sass resolves ⁠<code>$spacing-unit * 1.5</code> during build – outputting clean values that can render identically in legacy IE and Chrome Canary. Although this is increasingly a moot point when wanting <a href="https://utopia.fyi/">fluid changes across browser sizes</a>.</p>
<h3 id="build-time-power-plays" tabindex="-1">Build-Time Power Plays</h3>
<h4 id="utility-class-factories" tabindex="-1">Utility Class Factories</h4>
<p>Need to provide your <a href="https://www.alwaystwisted.com/articles/creating-utility-classes-with-design-tokens-using-sass">design decisions as utility classes</a>? Sass loops can help with that (although, if you’re implementing Design Tokens you can generate these using something like Style Dictionary (I will be working on an anrticle about this as part of my <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-1">Design Tokens Workflow Series</a> soon.</p>
<h3 id="design-system-bedrock" tabindex="-1">Design System Bedrock</h3>
<h4 id="breakpoint-clarity" tabindex="-1">Breakpoint Clarity</h4>
<p>Until <a href="https://www.w3.org/TR/mediaqueries-5/#custom-mq">⁠@custom-media</a> matures and gets into browsers, Sass variables help to tame responsive chaos.</p>
<h4 id="performance-critical-math" tabindex="-1">Performance-Critical Math</h4>
<p>If you have a lot of scales for things like spacing, typography or colour perhaps you don’t want the browser to make those calculations if they’re not going to change. Using Sass will help with any possible performance issues of an over reliance on CSS custom properties for everything.</p>
<h4 id="hard-coded-themes" tabindex="-1">Hard-Coded Themes</h4>
<p>When light/dark mode gets decided at build time (CMS page type, A/B test group), Sass maps can generate lean CSS.
Sass variables thrive when values need to be <strong>set in stone</strong> after compilation. They're the mason's chisel – uncompromising, precise, and leaving no runtime debris.</p>
<h2 id="combining-both-with-a-hybrid-approach" tabindex="-1">Combining Both With A Hybrid Approach</h2>
<p>CSS custom properties and Sass variables aren't sworn enemies – they' can be great collaborators in a layered architecture.
This hybrid model can treat Sass as the source of truth and CSS variables as the delivery mechanism for runtime flexibility and at the same time allow you to “set things in stone” that will never change in Sass.
<strong>Layered Architecture</strong></p>
<table>
<thead>
<tr>
<th>Layer</th>
<th>Purpose</th>
<th>Example</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Sass Layer</strong></td>
<td>Compile-time constants</td>
<td><code>⁠$gap: 1.125rem;</code></td>
</tr>
<tr>
<td><strong>CSS Layer</strong></td>
<td>Runtime-adjustable variables</td>
<td><code>⁠--component-spacing: #{$gap};</code></td>
</tr>
</tbody>
</table>
<h2 id="a-decision-tree" tabindex="-1">A Decision Tree</h2>
<p>This isn’t about right vs. wrong – it’s about matching the tools to the needs of the design, the team, and the product.
This table isn’t perdurable and it can and does change from project to project depending on requirements I find it useful to go through at times.</p>
<table>
<thead>
<tr>
<th>Factor</th>
<th>CSS Custom Property</th>
<th>Sass Variable</th>
</tr>
</thead>
<tbody>
<tr>
<td>Runtime changes</td>
<td>✅</td>
<td>❌</td>
</tr>
<tr>
<td>CMS exposure</td>
<td>✅</td>
<td>❌</td>
</tr>
<tr>
<td>Theming</td>
<td>✅</td>
<td>Limited</td>
</tr>
<tr>
<td>Math operations</td>
<td>Basic (⁠calc())</td>
<td>Advanced</td>
</tr>
<tr>
<td>Browser support</td>
<td>IE11+ (with polyfills)</td>
<td>Universal</td>
</tr>
</tbody>
</table>
<p>(although this is ususally thought through rather than checking an actual table).</p>
<h2 id="final-thoughts" tabindex="-1">Final Thoughts</h2>
<p>The interplay between Sass variables and CSS custom properties should be a strategic partnership. Over nearly a decade of evolving web practices, one truth persists: robust systems balance rigidity with adaptability. Sass anchors the immutable, CSS custom properties breathe life into any required fluidity.</p>
<p>Resilient systems should layer these tools intentionally. Let Sass handle the the design decisions that won’t change, heavy math and legacy support, while CSS variables manage any dynamicism required.</p>
<p>As browsers advance, the lines may blur – but the principles endure. Choose Sass for what must and should stay fixed, CSS for what needs to change.</p>
<p>After all, the best architectures aren’t built with tools, but with informed decisions about <em>when</em> to wield them.</p>
<p>(a little thanks for <a href="https://bell.bz">Andy Bell</a> for a little 'sense checking' along the way ❤️).</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 10) - Creating Multiple Themes with Style Dictionary</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-10.html"/>
      <updated>2025-04-02T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-10.html</id>
      <content type="html">
        <![CDATA[
        <p>In this tutorial series on design tokens and Style Dictionary, we have recently looked at power of <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-9">multi-brand theming</a>. Now, let's delve into creating multiple themes for a single brand.</p>
<p>Imagine having a personal website or brand that shines differently with each season, featuring special editions, or festive themes. The ability to seamlessly switch between these adds a layer of personalisation and fun engagement that can resonate with your readers.</p>
<h2 id="setting-up-token-layers-for-themes" tabindex="-1">Setting Up Token Layers for Themes</h2>
<p>Like in the <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-9">last article</a>, we will create distinct design tokens for each theme in the base layer and a single set of tokens in the semantic layer that reference the base layer.</p>
<h3 id="theme-specific-base-tokens" tabindex="-1">Theme-Specific Base Tokens</h3>
<p>For each theme, we define respective colour, typography, and spacing tokens to create visually distinct presentations. I’ll only provide the colour tokens in the article as a demonstration. You can <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/10-theming">can find all of the code in the github repo</a>.</p>
<p><strong>tokens/base/theme1/colors.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#0D6EFD"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#6C757D"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#FFFFFF"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#212529"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"accent"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#FFC107"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/base/theme2/colors.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#212529"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#343A40"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#121212"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#E9ECEF"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"accent"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#17A2B8"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/base/theme3/colors.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#FFC107"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#F44336"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#FFF4E0"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#333333"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"accent"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#4CAF50"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="shared-semantic-tokens" tabindex="-1">Shared Semantic Tokens</h3>
<p>The semantic tokens maintain consistency across all themes by referencing the appropriate theme base tokens, again I’ll only show the design tokens for the colours in the semantic layer also.</p>
<p><strong>tokens/semantic/colors.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"default"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.background}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"default"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.text}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"action"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.primary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.secondary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"highlight"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.accent}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="configuring-style-dictionary" tabindex="-1">Configuring Style Dictionary</h2>
<p>This file organises how the tokens are processed and how the resulting CSS files are generated. Let's explore the setup:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> globSync <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'glob'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token comment">// The themes we want to generate</span>
<span class="token keyword">const</span> themes <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'theme1'</span><span class="token punctuation">,</span> <span class="token string">'theme2'</span><span class="token punctuation">,</span> <span class="token string">'theme3'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// The output formats we want to generate</span>
<span class="token keyword">const</span> formats <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'css'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

<span class="token comment">// Function to get config for a specific theme and format (theme tokens)</span>
<span class="token keyword">function</span> <span class="token function">getStyleDictionaryConfig</span><span class="token punctuation">(</span><span class="token parameter">theme<span class="token punctuation">,</span> format</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> platformConfig <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>

  <span class="token comment">// Add theme CSS files</span>
  platformConfig<span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">_theme</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> format<span class="token punctuation">,</span>
    <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">build/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/themes/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
    <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token punctuation">{</span>
        <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>theme<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
        <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/theme-wrapper</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
        <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/base/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>theme<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">themeName</span><span class="token operator">:</span> theme<span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/base/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>theme<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/**/*.tokens</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
      <span class="token string">'src/tokens/semantic/**/*.tokens'</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token literal-property property">platforms</span><span class="token operator">:</span> platformConfig<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// Only generate semantic once, not per theme</span>
<span class="token keyword">function</span> <span class="token function">getSemanticConfig</span><span class="token punctuation">(</span><span class="token parameter">format</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token string">'src/tokens/base/theme1/**/*.tokens'</span><span class="token punctuation">,</span> <span class="token comment">// Need the base tokens for reference</span>
      <span class="token string">'src/tokens/semantic/**/*.tokens'</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">_semantic</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> format<span class="token punctuation">,</span>
        <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">build/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/semantic/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
        <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
          <span class="token punctuation">{</span>
            <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">tokens.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
            <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/variables-semantic</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
            <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'src/tokens/semantic/'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
            <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// Helper function to safely get token value</span>
<span class="token keyword">function</span> <span class="token function">getTokenValue</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>token <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>original <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$value<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>token <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> token<span class="token punctuation">.</span>value<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">return</span> token<span class="token punctuation">.</span>value<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// Register custom format for CSS theme wrapper with class selector</span>
StyleDictionary<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>formats<span class="token punctuation">[</span><span class="token string">'css/theme-wrapper'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>
  dictionary<span class="token punctuation">,</span>
  options<span class="token punctuation">,</span>
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> themeName <span class="token operator">=</span> options<span class="token punctuation">.</span>themeName <span class="token operator">||</span> <span class="token string">'default'</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> tokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
    token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/base/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>themeName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>
    <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Theme </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>themeName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> has </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>tokens<span class="token punctuation">.</span>length<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> tokens for theme wrapper</span><span class="token template-punctuation string">`</span></span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> variables <span class="token operator">=</span> tokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> name <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> value <span class="token operator">=</span> <span class="token function">getTokenValue</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>

      <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>themeName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>variables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n}</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom format for CSS semantic variables with ds- prefix</span>
StyleDictionary<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>formats<span class="token punctuation">[</span><span class="token string">'css/variables-semantic'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>
  dictionary<span class="token punctuation">,</span>
  options<span class="token punctuation">,</span>
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> semanticTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
    token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'src/tokens/semantic/'</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> variables <span class="token operator">=</span> semanticTokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> name <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> description <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$description <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">;</span>

      <span class="token keyword">const</span> referenceValue <span class="token operator">=</span> <span class="token function">getTokenValue</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>
        <span class="token keyword">typeof</span> referenceValue <span class="token operator">===</span> <span class="token string">'string'</span> <span class="token operator">&amp;&amp;</span>
        referenceValue<span class="token punctuation">.</span><span class="token function">startsWith</span><span class="token punctuation">(</span><span class="token string">'{'</span><span class="token punctuation">)</span>
      <span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> refPath <span class="token operator">=</span> referenceValue<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">const</span> cssVarName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>refPath<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

        <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --ds-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cssVarName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --ds-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>referenceValue<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">:root {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>variables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n}</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token comment">// Loop through each theme and format and build theme tokens</span>
themes<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">theme</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  formats<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">format</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Building </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> tokens for </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>theme<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">...</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> sd <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token function">getStyleDictionaryConfig</span><span class="token punctuation">(</span>theme<span class="token punctuation">,</span> format<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// For each platform in the config</span>
    Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>sd<span class="token punctuation">.</span>config<span class="token punctuation">.</span>platforms<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">platform</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      sd<span class="token punctuation">.</span><span class="token function">buildPlatform</span><span class="token punctuation">(</span>platform<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Build semantic tokens once for each format</span>
formats<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">format</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Building </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> semantic tokens...</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> sd <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token function">getSemanticConfig</span><span class="token punctuation">(</span>format<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// For each platform in the config</span>
  Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>sd<span class="token punctuation">.</span>config<span class="token punctuation">.</span>platforms<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">platform</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    sd<span class="token punctuation">.</span><span class="token function">buildPlatform</span><span class="token punctuation">(</span>platform<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="key-components-of-this-configuration" tabindex="-1">Key Components of this configuration</h3>
<h4 id="creating-the-style-dictionary-instance" tabindex="-1">Creating the Style Dictionary Instance</h4>
<p>This configuration manages both theme-specific styles and a unified semantic layer. For each theme, a distinct set of base tokens is compiled. This setup allows themes to be visually unique while maintaining global consistency through central semantic tokens.</p>
<p><strong>Highlights:</strong></p>
<ul>
<li><strong>Theme-Specific Configurations</strong>: Each theme (e.g., ⁠<code>theme1</code>, <code>⁠theme2</code>, <code>⁠theme3</code>) is processed to generate a ⁠.css file wrapped in class selectors (e.g., ⁠.<code>theme1 { ... }</code>).</li>
<li><strong>Single Semantic Output</strong>: Generates a single semantic token file, ensuring consistent semantic definitions across themes.</li>
</ul>
<h4 id="custom-format-registration" tabindex="-1">Custom Format Registration</h4>
<p>The configuration includes custom formats such as <code>⁠css/theme-wrapper</code> for creating class-based CSS files and ⁠<code>css/variables-semantic</code> for generating semantically consistent variables with a ⁠<code>ds-</code> prefix.</p>
<p><strong>Highlights:</strong></p>
<ul>
<li><strong>Theme Wrappers</strong>: Theme-specific files are wrapped in class selectors, allowing easy theme switching via class manipulation.</li>
<li><strong>Consistent Semantics</strong>: Shared semantic tokens are marked with a <code>⁠ds-</code> prefix, maintaining a clear separation between base and semantic layers.</li>
</ul>
<h4 id="building-all-platforms" tabindex="-1">Building All Platforms</h4>
<p>The script loops through each theme and format, compiling the necessary CSS outputs. Maintaining structured processes ensures efficient builds and organised outputs, ready for immediate integration into modern web projects</p>
<h2 id="example-outputs" tabindex="-1">Example Outputs</h2>
<p>The Style Dictionary script creates theme-specific CSS files and a set of semantic CSS tokens that ensure stylistic consistency across themes. Here’s an example at what these outputs look like:</p>
<h3 id="generated-base-layer-css" tabindex="-1">Generated Base Layer CSS</h3>
<p>The theme-specific CSS classes are wrapped in class selectors, allowing easy switching between themes on your website by altering the class of an element (like the <code>body</code> or <code>html</code> itself):</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.theme1</span> <span class="token punctuation">{</span>
  <span class="token property">--color-base-primary</span><span class="token punctuation">:</span> #0d6efd<span class="token punctuation">;</span>
  <span class="token property">--color-base-secondary</span><span class="token punctuation">:</span> #6c757d<span class="token punctuation">;</span>
  <span class="token property">--color-base-background</span><span class="token punctuation">:</span> #ffffff<span class="token punctuation">;</span>
  <span class="token property">--color-base-text</span><span class="token punctuation">:</span> #212529<span class="token punctuation">;</span>
  <span class="token property">--color-base-accent</span><span class="token punctuation">:</span> #ffc107<span class="token punctuation">;</span>
  <span class="token property">--spacing-base-xs</span><span class="token punctuation">:</span> 4px<span class="token punctuation">;</span>
  <span class="token property">--spacing-base-sm</span><span class="token punctuation">:</span> 8px<span class="token punctuation">;</span>
  <span class="token property">--spacing-base-md</span><span class="token punctuation">:</span> 16px<span class="token punctuation">;</span>
  <span class="token property">--spacing-base-lg</span><span class="token punctuation">:</span> 24px<span class="token punctuation">;</span>
  <span class="token property">--spacing-base-xl</span><span class="token punctuation">:</span> 32px<span class="token punctuation">;</span>
  <span class="token property">--font-family-primary</span><span class="token punctuation">:</span> <span class="token string">'Roboto'</span><span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
  <span class="token property">--font-family-secondary</span><span class="token punctuation">:</span> <span class="token string">'Open Sans'</span><span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
  <span class="token property">--font-weight-regular</span><span class="token punctuation">:</span> 400<span class="token punctuation">;</span>
  <span class="token property">--font-weight-bold</span><span class="token punctuation">:</span> 700<span class="token punctuation">;</span>
  <span class="token property">--font-size-small</span><span class="token punctuation">:</span> 14px<span class="token punctuation">;</span>
  <span class="token property">--font-size-medium</span><span class="token punctuation">:</span> 16px<span class="token punctuation">;</span>
  <span class="token property">--font-size-large</span><span class="token punctuation">:</span> 24px<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="generated-semantic-layer-css" tabindex="-1">Generated Semantic Layer CSS</h3>
<p>This output establishes the shared semantics with a <code>ds-</code> prefix, simplifying theme maintenance. The <code>:root</code> here acts as a global baseline for semantic values:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--ds-color-background-default</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-background<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-color-text-default</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-text<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-color-action-primary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-primary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-color-action-secondary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-secondary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-color-action-highlight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-accent<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-element-xsmall</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-xs<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-element-small</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-sm<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-element-medium</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-md<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-element-large</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-lg<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-element-xlarge</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-xl<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-layout-small</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-md<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-layout-medium</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-lg<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-layout-large</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-xl<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-heading-fontFamily</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-family-primary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-heading-fontWeight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-weight-bold<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-heading-fontSize</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-large<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-body-fontFamily</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-family-secondary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-body-fontWeight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-weight-regular<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-body-fontSize</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-medium<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-caption-fontFamily</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-family-secondary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-caption-fontWeight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-weight-regular<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-caption-fontSize</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-small<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>By employing this approach, Style Dictionary can facilitate a unified and cohesive theming experience. Your themes can uniquely shine while maintaining a consistent design language across your website.
With the thematic CSS structure in place, you can integrate a theme switcher using JavaScript allowing your visitors to choose how they want to have your site look.</p>
<p>In the previous article we addressed multi-brand theming and with a few small changes this configuration has focused on tailoring multiple themes within a single brand or personal website. This approach allows you to adapt your design system to evolving needs while ensuring visual harmony.</p>
<p>Embracing these strategies provides flexible theming options to meet various needs, whether for personal projects or larger brand applications. These methods help reinforce the strength of your design system.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 9) - Implementing Multi-Brand Theming with Style Dictionary</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-9.html"/>
      <updated>2025-04-01T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-9.html</id>
      <content type="html">
        <![CDATA[
        <p>Businesses often juggle multiple brand identities to connect with a variety of audiences. This approach can translate into distinct visual elements (colors, typography, and other styles) that uniquely represent a brand. A robust design system is essential to juggle these brands styles while ensuring a seamless experience across all platforms.
In the last couple of tutorials in this series, we explored how to <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-7">implement light and dark modes using design tokens</a> and <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-7">strategies for managing and organising these tokens effectively</a>. This tutorial delves into the world of multi-brand theming, a critical approach that enables organisations to maintain cohesive design frameworks while embracing brand diversity.</p>
<h2 id="a-quick-recap" tabindex="-1">A quick recap</h2>
<p>For this article, we’re going to make use of <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-6">two layers of design tokens</a> to help with keeping our brands consistent when the output is being used. We will use base tokens and semantic tokens.</p>
<h3 id="base-tokens" tabindex="-1">Base Tokens</h3>
<p>Base tokens represent the raw, literal values that form the foundation of your design system. They can include:</p>
<ul>
<li>Specific hex values for colours (e.g., ⁠#BA1A2A, #006BC9)</li>
<li>Precise measurements for spacing (e.g., ⁠4px, ⁠16px)</li>
<li>Font families and weights (e.g., ⁠'Roboto', ⁠700)
Base tokens are typically named descriptively to reflect their inherent properties rather than their usage:</li>
</ul>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"blue500"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#007BFF"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"gray100"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#F5F5F5"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"size"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"4"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"4px"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"16"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"16px"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="semantic-tokens" tabindex="-1">Semantic Tokens</h3>
<p>Semantic tokens add meaning and context by mapping to base tokens. They can describe the purpose or usage of a token rather than its visual properties:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.blue500}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.gray100}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"small"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{size.4}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"medium"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{size.16}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>By using semantic tokens, teams can update the underlying base token (e.g., changing ⁠blue500 from ⁠#0066CC to #276AB3) without needing to change references throughout the codebase.</p>
<h2 id="setting-up-token-layers-for-brands" tabindex="-1">Setting Up Token Layers for Brands</h2>
<p>When implementing multiple brands, each brand requires its own set of base tokens that semantic tokens can reference. This allows you to maintain consistent semantic naming while varying the visual presentation across the brands.
Let's explore how to organise tokens for a Design System for three distinct brands:</p>
<h3 id="brand-specific-base-tokens" tabindex="-1">Brand-Specific Base Tokens</h3>
<p>For this example, we'll create dedicated sets of base tokens for each of WWE's iconic brands: Raw, SmackDown, and NXT. These tokens will encompass essential design elements such as colours, typography, and spacing, ensuring each brand maintains a unique identity while supporting a cohesive design system.
<strong>tokens/base/raw/colors.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#d7182a"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#A3A3A3"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#F5F5F5"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#1C1C1C"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"accent"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#FFD700"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/base/raw/typography.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"font"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"family"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"'Roboto', sans-serif"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"'Open Sans', sans-serif"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"weight"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"regular"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"400"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"bold"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"700"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"size"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"small"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"14px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"medium"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"16px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"large"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"24px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/base/raw/spacing.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"xs"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"4px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"sm"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"8px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"md"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"16px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"lg"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"24px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"xl"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"32px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Now, let's define similar token files for Smackdown and NXT, each with their unique values:
<strong>tokens/base/smackdown/colors.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#9933CC"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#495057"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#F8F9FA"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#343A40"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"accent"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#FF5722"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/base/smackdown/typography.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"font"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"family"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"'Montserrat', sans-serif"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"'Lato', sans-serif"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"weight"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"regular"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"400"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"bold"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"600"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"size"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"small"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"12px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"medium"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"15px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"large"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"22px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/base/smackdown/spacing.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"xs"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"2px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"sm"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"6px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"md"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"12px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"lg"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"20px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"xl"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"28px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/base/nxt/colors.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#2E7D32"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#546E7A"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#E8F5E9"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#1B5E20"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"accent"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#F57F17"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/base/nxt/typography.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"font"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"family"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"'Poppins', sans-serif"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"'Merriweather', serif"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"weight"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"regular"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"300"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"bold"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"500"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"size"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"small"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"16px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"medium"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"18px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"large"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"26px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/base/nxt/spacing.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"xs"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"5px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"sm"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"10px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"md"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"20px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"lg"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"30px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"xl"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"40px"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="shared-semantic-tokens" tabindex="-1">Shared Semantic Tokens</h3>
<p>The key advantage of this approach is that semantic tokens can remain consistent across all themes, using a single shared naming convention with the ⁠<code>ds-</code> prefix:
<strong>tokens/semantic/colors.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"default"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.background}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"default"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.text}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"action"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.primary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.secondary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"highlight"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.accent}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/semantic/typography.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"typography"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"heading"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"fontFamily"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{font.family.primary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"fontWeight"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{font.weight.bold}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"fontSize"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{font.size.large}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"body"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"fontFamily"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{font.family.secondary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"fontWeight"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{font.weight.regular}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"fontSize"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{font.size.medium}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"caption"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"fontFamily"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{font.family.secondary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"fontWeight"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{font.weight.regular}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"fontSize"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{font.size.small}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/semantic/spacing.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"element"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"xsmall"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{spacing.base.xs}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"small"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{spacing.base.sm}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"medium"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{spacing.base.md}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"large"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{spacing.base.lg}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"xlarge"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{spacing.base.xl}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"layout"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"small"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{spacing.base.md}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"medium"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{spacing.base.lg}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"large"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{spacing.base.xl}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>This structure allows you to swap out the base layer for each brand while maintaining the semantic relationships, creating a consistent naming convention regardless of which brand is being implemented.</p>
<h2 id="creating-brands-with-style-dictionary-using-token-layers" tabindex="-1">Creating Brands with Style Dictionary Using Token Layers</h2>
<p>With our token structure established, we can now configure Style Dictionary to compile brand-specific outputs while preserving the layer relationships. We'll generate both CSS custom properties and Sass variables to provide flexibility for different project requirements.</p>
<h3 id="configuring-style-dictionary" tabindex="-1">Configuring Style Dictionary</h3>
<p>The following configuration compiles our tokens into CSS and Sass outputs for each theme:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> globSync <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'glob'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token comment">// The brands we want to generate</span>
<span class="token keyword">const</span> brands <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'raw'</span><span class="token punctuation">,</span> <span class="token string">'smackdown'</span><span class="token punctuation">,</span> <span class="token string">'nxt'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// The output formats we want to generate</span>
<span class="token keyword">const</span> formats <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'css'</span><span class="token punctuation">,</span> <span class="token string">'scss'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

<span class="token comment">// Function to get config for a specific brand and format (base tokens)</span>
<span class="token keyword">function</span> <span class="token function">getStyleDictionaryConfig</span><span class="token punctuation">(</span><span class="token parameter">brand<span class="token punctuation">,</span> format</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// Base platform configuration (for both CSS and SCSS)</span>
  <span class="token keyword">const</span> platformConfig <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">_base</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> format<span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">build/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/base/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>brand<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/variables</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
            token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/base/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>brand<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>

  <span class="token comment">// Removed the brand CSS files configuration here</span>

  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/base/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>brand<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/**/*.tokens</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
      <span class="token string">'src/tokens/semantic/**/*.tokens'</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token literal-property property">platforms</span><span class="token operator">:</span> platformConfig<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// Only generate semantic once, not per brand</span>
<span class="token keyword">function</span> <span class="token function">getSemanticConfig</span><span class="token punctuation">(</span><span class="token parameter">format</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token string">'src/tokens/base/raw/**/*.tokens'</span><span class="token punctuation">,</span> <span class="token comment">// a brand (any brand) is needed to generate semantic tokens</span>
      <span class="token string">'src/tokens/semantic/**/*.tokens'</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">_semantic</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> format<span class="token punctuation">,</span>
        <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">build/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/semantic/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
        <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
          <span class="token punctuation">{</span>
            <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">tokens.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
            <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/variables-semantic</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
            <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'src/tokens/semantic/'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
            <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
              <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// Helper function to safely get token value</span>
<span class="token keyword">function</span> <span class="token function">getTokenValue</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>token <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>original <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$value<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>token <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> token<span class="token punctuation">.</span>value<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">return</span> token<span class="token punctuation">.</span>value<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// Removed the brand wrapper format registration</span>

<span class="token comment">// Register custom format for CSS semantic variables with ds- prefix</span>
StyleDictionary<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>formats<span class="token punctuation">[</span><span class="token string">'css/variables-semantic'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>
  dictionary<span class="token punctuation">,</span>
  options<span class="token punctuation">,</span>
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> semanticTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
    token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'src/tokens/semantic/'</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> variables <span class="token operator">=</span> semanticTokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> name <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> description <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$description <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">;</span>

      <span class="token keyword">const</span> referenceValue <span class="token operator">=</span> <span class="token function">getTokenValue</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>
        <span class="token keyword">typeof</span> referenceValue <span class="token operator">===</span> <span class="token string">'string'</span> <span class="token operator">&amp;&amp;</span>
        referenceValue<span class="token punctuation">.</span><span class="token function">startsWith</span><span class="token punctuation">(</span><span class="token string">'{'</span><span class="token punctuation">)</span>
      <span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> refPath <span class="token operator">=</span> referenceValue<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">const</span> cssVarName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>refPath<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

        <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --ds-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cssVarName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --ds-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>referenceValue<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">:root {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>variables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n}</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom format for SCSS semantic variables with ds- prefix</span>
StyleDictionary<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>formats<span class="token punctuation">[</span><span class="token string">'scss/variables-semantic'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>
  dictionary<span class="token punctuation">,</span>
  options<span class="token punctuation">,</span>
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> semanticTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
    token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'src/tokens/semantic/'</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> variables <span class="token operator">=</span> semanticTokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> name <span class="token operator">=</span> token<span class="token punctuation">.</span>path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> description <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$description <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">;</span>

      <span class="token keyword">const</span> referenceValue <span class="token operator">=</span> <span class="token function">getTokenValue</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>
        <span class="token keyword">typeof</span> referenceValue <span class="token operator">===</span> <span class="token string">'string'</span> <span class="token operator">&amp;&amp;</span>
        referenceValue<span class="token punctuation">.</span><span class="token function">startsWith</span><span class="token punctuation">(</span><span class="token string">'{'</span><span class="token punctuation">)</span>
      <span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> refPath <span class="token operator">=</span> referenceValue<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">$ds-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: $</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>refPath<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> // </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">$ds-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>referenceValue<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> // </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> variables<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token comment">// Loop through each brand and format and build base tokens</span>
brands<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">brand</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  formats<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">format</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Building </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> tokens for </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>brand<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">...</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> sd <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token function">getStyleDictionaryConfig</span><span class="token punctuation">(</span>brand<span class="token punctuation">,</span> format<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// For each platform in the config</span>
    Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>sd<span class="token punctuation">.</span>config<span class="token punctuation">.</span>platforms<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">platform</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      sd<span class="token punctuation">.</span><span class="token function">buildPlatform</span><span class="token punctuation">(</span>platform<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Build semantic tokens once for each format</span>
formats<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">format</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Building </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>format<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> semantic tokens...</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> sd <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token function">getSemanticConfig</span><span class="token punctuation">(</span>format<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// For each platform in the config</span>
  Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>sd<span class="token punctuation">.</span>config<span class="token punctuation">.</span>platforms<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">platform</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    sd<span class="token punctuation">.</span><span class="token function">buildPlatform</span><span class="token punctuation">(</span>platform<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="explanation-of-key-components" tabindex="-1">Explanation of Key Components</h3>
<h4 id="creating-the-style-dictionary-instance" tabindex="-1">Creating the Style Dictionary Instance</h4>
<p>This script first configures Style Dictionary to handle base tokens for multiple brands. Each brand has its own set of base tokens designated by its unique file paths in the ⁠<code>src/tokens/base/</code> directory. The script systematically builds these tokens for each brand in the specified output formats (CSS and SCSS).
<strong>Key Points:</strong></p>
<ul>
<li><strong>Brands Configuration:</strong> The ⁠<code>brands</code> array specifies the brand names, which correspond to token file directories.</li>
<li><strong>Formats:</strong> The <code>⁠formats</code> array ensures outputs for both CSS and SCSS.</li>
<li><strong>Configuration Function:</strong> ⁠<code>getStyleDictionaryConfig</code> dynamically generates the configuration for each brand and format combination.</li>
<li><strong>Token Filtering:</strong> Filters help map input token files correctly to their corresponding brands.</li>
</ul>
<h4 id="registering-a-custom-format-for-semantic-tokens" tabindex="-1">Registering a Custom Format for Semantic Tokens</h4>
<p>The script registers custom formats to generate variables with a ⁠<code>ds-</code> namespace in both CSS and SCSS. This design ensures semantic tokens remain consistent across brands, leveraging shared properties.
<strong>Highlights:</strong></p>
<ul>
<li><strong>CSS Variable Registration:</strong> Custom functions format CSS with the <code>⁠ds-</code> prefix, ensuring clarity and consistency.</li>
<li><strong>Semantic Generation:</strong> Shared semantic tokens only need to be built once, fostering efficiency.
<strong>Building All Platforms</strong>
The script uses loops to iterate over each brand and format, systematically building and compiling tokens. It ensures separate brand builds to encapsulate unique identities while generating a single semantic output, unifying shared visual elements across the system.
Finally, a console log indicates successful build completion, providing clear feedback on the process and confirming that all configurations have been executed correctly.</li>
</ul>
<h3 id="the-generated-outputs" tabindex="-1">The Generated Outputs</h3>
<p>After running the build script, Style Dictionary will generate the following files for each brand:
<strong>CSS Custom Properties (build/css/raw/base.css)</strong></p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-base-primary</span><span class="token punctuation">:</span> #d7182a<span class="token punctuation">;</span>
  <span class="token property">--color-base-secondary</span><span class="token punctuation">:</span> #8b0000<span class="token punctuation">;</span>
  <span class="token property">--color-base-background</span><span class="token punctuation">:</span> #ffcdd2<span class="token punctuation">;</span>
  <span class="token property">--color-base-text</span><span class="token punctuation">:</span> #000000<span class="token punctuation">;</span>
  <span class="token property">--color-base-accent</span><span class="token punctuation">:</span> #ffd700<span class="token punctuation">;</span>
  <span class="token property">--spacing-base-xs</span><span class="token punctuation">:</span> 4px<span class="token punctuation">;</span>
  <span class="token property">--spacing-base-sm</span><span class="token punctuation">:</span> 8px<span class="token punctuation">;</span>
  <span class="token property">--spacing-base-md</span><span class="token punctuation">:</span> 16px<span class="token punctuation">;</span>
  <span class="token property">--spacing-base-lg</span><span class="token punctuation">:</span> 24px<span class="token punctuation">;</span>
  <span class="token property">--spacing-base-xl</span><span class="token punctuation">:</span> 32px<span class="token punctuation">;</span>
  <span class="token property">--font-family-primary</span><span class="token punctuation">:</span> <span class="token string">'Roboto'</span><span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
  <span class="token property">--font-family-secondary</span><span class="token punctuation">:</span> <span class="token string">'Open Sans'</span><span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
  <span class="token property">--font-weight-regular</span><span class="token punctuation">:</span> 400<span class="token punctuation">;</span>
  <span class="token property">--font-weight-bold</span><span class="token punctuation">:</span> 700<span class="token punctuation">;</span>
  <span class="token property">--font-size-small</span><span class="token punctuation">:</span> 14px<span class="token punctuation">;</span>
  <span class="token property">--font-size-medium</span><span class="token punctuation">:</span> 16px<span class="token punctuation">;</span>
  <span class="token property">--font-size-large</span><span class="token punctuation">:</span> 24px<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>CSS Custom Properties (build/css/semantic/tokens.css)</strong></p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--ds-color-background-default</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-background<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-color-text-default</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-text<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-color-action-primary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-primary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-color-action-secondary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-secondary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-color-action-highlight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-accent<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-heading-fontFamily</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-family-primary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-heading-fontWeight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-weight-bold<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-heading-fontSize</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-large<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-body-fontFamily</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-family-secondary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-body-fontWeight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-weight-regular<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-body-fontSize</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-medium<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-caption-fontFamily</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-family-secondary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-caption-fontWeight</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-weight-regular<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-typography-caption-fontSize</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-small<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-element-xsmall</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-xs<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-element-small</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-sm<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-element-medium</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-md<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-element-large</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-lg<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-element-xlarge</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-xl<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-layout-small</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-md<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-layout-medium</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-lg<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--ds-spacing-layout-large</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--spacing-base-xl<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>Sass Variables (build/scss/raw/base.scss)</strong></p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$color-base-primary</span></span><span class="token punctuation">:</span> #d7182a<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$color-base-secondary</span></span><span class="token punctuation">:</span> #8b0000<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$color-base-background</span></span><span class="token punctuation">:</span> #ffcdd2<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$color-base-text</span></span><span class="token punctuation">:</span> #000000<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$color-base-accent</span></span><span class="token punctuation">:</span> #ffd700<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-base-xs</span></span><span class="token punctuation">:</span> 4px<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-base-sm</span></span><span class="token punctuation">:</span> 8px<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-base-md</span></span><span class="token punctuation">:</span> 16px<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-base-lg</span></span><span class="token punctuation">:</span> 24px<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-base-xl</span></span><span class="token punctuation">:</span> 32px<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$font-family-primary</span></span><span class="token punctuation">:</span> <span class="token string">'Roboto'</span><span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$font-family-secondary</span></span><span class="token punctuation">:</span> <span class="token string">'Open Sans'</span><span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$font-weight-regular</span></span><span class="token punctuation">:</span> 400<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$font-weight-bold</span></span><span class="token punctuation">:</span> 700<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$font-size-small</span></span><span class="token punctuation">:</span> 14px<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$font-size-medium</span></span><span class="token punctuation">:</span> 16px<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$font-size-large</span></span><span class="token punctuation">:</span> 24px<span class="token punctuation">;</span></code></pre>
<p><strong>Sass Variables (build/scss/semantic/tokens.scss)</strong></p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$ds-color-background-default</span></span><span class="token punctuation">:</span> <span class="token variable">$color-base-background</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-color-text-default</span></span><span class="token punctuation">:</span> <span class="token variable">$color-base-text</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-color-action-primary</span></span><span class="token punctuation">:</span> <span class="token variable">$color-base-primary</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-color-action-secondary</span></span><span class="token punctuation">:</span> <span class="token variable">$color-base-secondary</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-color-action-highlight</span></span><span class="token punctuation">:</span> <span class="token variable">$color-base-accent</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-typography-heading-fontFamily</span></span><span class="token punctuation">:</span> <span class="token variable">$font-family-primary</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-typography-heading-fontWeight</span></span><span class="token punctuation">:</span> <span class="token variable">$font-weight-bold</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-typography-heading-fontSize</span></span><span class="token punctuation">:</span> <span class="token variable">$font-size-large</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-typography-body-fontFamily</span></span><span class="token punctuation">:</span> <span class="token variable">$font-family-secondary</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-typography-body-fontWeight</span></span><span class="token punctuation">:</span> <span class="token variable">$font-weight-regular</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-typography-body-fontSize</span></span><span class="token punctuation">:</span> <span class="token variable">$font-size-medium</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-typography-caption-fontFamily</span></span><span class="token punctuation">:</span> <span class="token variable">$font-family-secondary</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-typography-caption-fontWeight</span></span><span class="token punctuation">:</span> <span class="token variable">$font-weight-regular</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-typography-caption-fontSize</span></span><span class="token punctuation">:</span> <span class="token variable">$font-size-small</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-spacing-element-xsmall</span></span><span class="token punctuation">:</span> <span class="token variable">$spacing-base-xs</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-spacing-element-small</span></span><span class="token punctuation">:</span> <span class="token variable">$spacing-base-sm</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-spacing-element-medium</span></span><span class="token punctuation">:</span> <span class="token variable">$spacing-base-md</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-spacing-element-large</span></span><span class="token punctuation">:</span> <span class="token variable">$spacing-base-lg</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-spacing-element-xlarge</span></span><span class="token punctuation">:</span> <span class="token variable">$spacing-base-xl</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-spacing-layout-small</span></span><span class="token punctuation">:</span> <span class="token variable">$spacing-base-md</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-spacing-layout-medium</span></span><span class="token punctuation">:</span> <span class="token variable">$spacing-base-lg</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$ds-spacing-layout-large</span></span><span class="token punctuation">:</span> <span class="token variable">$spacing-base-xl</span><span class="token punctuation">;</span></code></pre>
<p>Similar outputs will be generated for the othrt brands, each with their unique values but maintaining the same semantic structure.</p>
<p>You can find the <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/09-multi-brand-theming">code for this article on Github</a>.</p>
<p>Using Style Dictionary for multiple brands with a token layer strategy unlocks a suite of advantages that transform how we can approach design systems.</p>
<p>Here's why this approach stands out:</p>
<ol>
<li><strong>Seamless Consistency Across Platforms</strong>: With Style Dictionary, you can produce brand-specific tokens that cater to multiple platforms such as CSS, Sass, iOS, Android, and more. This ensures a uniform visual identity is maintained across all implementations.</li>
<li><strong>Centralised Brand Management</strong>: All brand definitions are housed within a single source of truth. This centralisation simplifies the update process and minimises inconsistencies, making maintenance a breeze.</li>
<li><strong>Scalability Built-In</strong>: As your product line expands, you can incorporate new brands without overhauling your entire system. Simply add new base token sets and watch your design system grow.</li>
<li><strong>Clear License of Separation</strong>: By distinguishing between raw values and their semantic meanings, both developers and designers can work more intuitively.</li>
<li><strong>Lowered Maintenance Load</strong>: By isolating modifications to the base layer, semantic tokens inherently mirror these updates. This can reduce overhead and maintains cohesion across your brands.
By harnessing the power of Design Tokens and Style Dictionary and a layered token architecture, teams can establish resilient and maintainable multi-brand systems.
As we continue to refine and evolve our design systems, using Design Tokens and integrating Style Dictionary presents a robust route toward flexible and scalable branding solutions. Stay tuned for our next installment, where we will dive into creating multiple themes for a single brand.</li>
</ol>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 8) - Implementing Light and Dark Mode with Style Dictionary (part 2)</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-8.html"/>
      <updated>2025-03-07T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-8.html</id>
      <content type="html">
        <![CDATA[
        <p>In the last article in this series <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-7">we looked at how we could convert our design tokens into CSS for light and dark modes using Style Dictionary</a>. We created some new formats to generate CSS that used <code>prefers-color-scheme</code> and also generate separate CSS files for both light and dark mode or a single CSS file that would incorporate both.
In this tutorial, we will explore two additional methods for implementing light and dark modes in your design system using Style Dictionary. Building on our previous tutorial, we will focus on how to add a data attribute or CSS class for dark mode, as well as generating relevant tokens using the CSS <code>light-dark()</code> function. These approaches enhance the flexibility and adaptability of your design system, allowing for a smoother user experience.</p>
<h2 id="adding-a-data-attribute-or-css-class-for-dark-mode" tabindex="-1">Adding a Data Attribute or CSS Class for Dark Mode</h2>
<p>To provide users with a seamless experience when toggling between light and dark modes, we can utilise a data attribute or CSS class. This method allows developers to apply dark mode styles conditionally based on the presence of a specific attribute or class in the HTML. Additionally, developers can implement a JavaScript function to toggle these modes dynamically, enabling users to switch modes with a button click.</p>
<h3 id="creating-some-design-tokens" tabindex="-1">Creating Some Design Tokens</h3>
<p>Again, we will have some base <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-6">layer tokens</a> to choose from at the semantic layer to provide meaningful, purposeful names for the design decisions for light and dark mode.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"white"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#FFFFFF"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"black"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#000000"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"gray"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"100"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#F7F7F7"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"200"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#E1E1E1"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"300"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#CFCFCF"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#B3B3B3"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"500"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#A0A0A0"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"600"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#7D7D7D"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"700"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#5A5A5A"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"800"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#3D3D3D"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"900"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#1A1A1A"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#007BFF"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#6C757D"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>We will then setup our semantic tokens like we did for <a href="localhost:8080/articles/a-design-tokens-workflow-part-7.html%23single-token-file-incorporating-light-and-dark-modes-(one-css-file)">single token file</a> in the last article in this series.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.white}"</span><span class="token punctuation">,</span>
      <span class="token property">"$mods"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"dark"</span><span class="token operator">:</span> <span class="token string">"{color.base.black}"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Background color for light mode."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.black}"</span><span class="token punctuation">,</span>
      <span class="token property">"$mods"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"dark"</span><span class="token operator">:</span> <span class="token string">"{color.base.white}"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Text color for light mode."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"card"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.200}"</span><span class="token punctuation">,</span>
        <span class="token property">"$mods"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"dark"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.800}"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Background color for cards in light mode."</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"border"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.600}"</span><span class="token punctuation">,</span>
        <span class="token property">"$mods"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"dark"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.400}"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Border color for cards in light mode."</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"button"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.primary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Primary button background color in dark mode."</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.secondary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Secondary button background color in dark mode."</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.white}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Text color for buttons in dark mode."</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="setting-up-the-build-process" tabindex="-1">Setting Up the Build Process</h3>
<p>We now need to set up the script that sets up the build process for generating CSS variables that accommodate both light and dark modes, including the necessary data attribute and CSS class.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> globSync <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'glob'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> tokenFiles <span class="token operator">=</span> <span class="token function">globSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens/**/*.tokens'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token constant">HEADER_COMMENT</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">/**
 * Do not edit directly, this file was auto-generated.
 */\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css_base</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/base/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'base'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">css_themed</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/combined/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables-themed'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>formats<span class="token punctuation">[</span><span class="token string">'css/variables-themed'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>
  dictionary<span class="token punctuation">,</span>
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> semanticTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
    token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'combined'</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> variables <span class="token operator">=</span> semanticTokens<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> <span class="token punctuation">{</span> name <span class="token punctuation">}</span> <span class="token operator">=</span> token<span class="token punctuation">;</span>
    <span class="token keyword">const</span> description <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$description<span class="token punctuation">;</span>
    <span class="token keyword">const</span> baseVariableName <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">[</span><span class="token string">'$value'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> lightCssVariableName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseVariableName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> darkModeValue <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$mods<span class="token operator">?.</span>dark<span class="token punctuation">;</span>
    <span class="token keyword">const</span> darkCssVariableName <span class="token operator">=</span> darkModeValue
      <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkModeValue
          <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span>
          <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span>
          <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span>
      <span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">light</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lightCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">dark</span><span class="token operator">:</span> darkCssVariableName
        <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span>
        <span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> lightVariables <span class="token operator">=</span> variables<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">v</span><span class="token punctuation">)</span> <span class="token operator">=></span> v<span class="token punctuation">.</span>light<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> darkVariables <span class="token operator">=</span> variables
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">v</span><span class="token punctuation">)</span> <span class="token operator">=></span> v<span class="token punctuation">.</span>dark<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>Boolean<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">HEADER_COMMENT</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">:root  {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lightVariables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n}\n\n@media (prefers-color-scheme: dark) {\n  :root{\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkVariables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n  }\n}\n\n[data-mode='dark'], .mode-dark {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkVariables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n}</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="explanation-of-the-script" tabindex="-1">Explanation of the Script</h3>
<ol>
<li><strong>Data Attribute and CSS Class</strong>: The generated CSS will include styles that apply when a [data-mode='dark'] attribute or a .mode-dark class is present. This provides flexibility in how dark mode styles are applied, allowing developers to choose the method that best fits their project.</li>
</ol>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// Data Attribute and CSS Class</span>
<span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">HEADER_COMMENT</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">:root  {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lightVariables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n}\n\n@media (prefers-color-scheme: dark) {\n  :root{\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkVariables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n  }\n}\n\n[data-mode='dark'], .mode-dark {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkVariables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n}</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span></code></pre>
<ol start="2">
<li><strong>CSS Variable Generation</strong>: The script extracts semantic tokens and generates CSS variables for both light and dark modes. The dark mode variables are included within a media query for automatic application based on user preferences, while also being available for manual toggling via the data attribute or class.</li>
</ol>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// CSS Variable Generation</span>
<span class="token keyword">const</span> variables <span class="token operator">=</span> semanticTokens<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">{</span> name <span class="token punctuation">}</span> <span class="token operator">=</span> token<span class="token punctuation">;</span>
  <span class="token keyword">const</span> description <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$description<span class="token punctuation">;</span>
  <span class="token keyword">const</span> baseVariableName <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">[</span><span class="token string">'$value'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> lightCssVariableName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseVariableName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> darkModeValue <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$mods<span class="token operator">?.</span>dark<span class="token punctuation">;</span>
  <span class="token keyword">const</span> darkCssVariableName <span class="token operator">=</span> darkModeValue
    <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkModeValue
        <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span>
    <span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">light</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lightCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
    <span class="token literal-property property">dark</span><span class="token operator">:</span> darkCssVariableName
      <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span>
      <span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="the-generated-css" tabindex="-1">The Generated CSS</h3>
<p>After running this build script, Style Dictionary will generate one CSS file for the colours in the semantic tokens layer. We now have CSS declarations that are nested within a data-attribute and CSS class.
This script also provides both ⁠prefers-color-scheme CSS declarations and styles based on data attributes or CSS classes, ensuring a comprehensive approach to theming. While the media query automatically detects user preferences for light or dark mode, the data attribute and CSS class allow users to manually toggle modes (using JavaScript).</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/**
 * Do not edit directly, this file was auto-generated.
 */</span>

<span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-black<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-card-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-200<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-card-border</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-600<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--button-background-primary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-primary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--button-background-secondary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-secondary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--button-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
  <span class="token selector">:root</span> <span class="token punctuation">{</span>
    <span class="token property">--color-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-black<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">--color-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">--color-card-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-800<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">--color-card-border</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-400<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token selector">[data-mode='dark'],
.mode-dark</span> <span class="token punctuation">{</span>
  <span class="token property">--color-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-black<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-card-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-800<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-card-border</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-400<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="generating-the-relevant-tokens-in-the-css-light-dark()-function" tabindex="-1">Generating the Relevant Tokens in the CSS light-dark() Function</h2>
<p>Another effective method for managing light and dark modes is to utilise a <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark">light-dark()</a> function in CSS. This function simplifies the process of switching between light and dark mode styles, allowing developers to specify how styles should adapt based on the user's preference</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p><a href="https://front-end.social/@sarajw">Sara Joy</a> has an excellent article on CSS-Tricks explaining the wonders of the <a href="https://css-tricks.com/come-to-the-light-dark-side/">light-dark() CSS function</a></p>
</div>
<h3 id="setting-up-the-build-process-1" tabindex="-1">Setting Up the Build Process</h3>
<p>Here’s how to implement the light-dark() function in your CSS:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> globSync <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'glob'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> tokenFiles <span class="token operator">=</span> <span class="token function">globSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens/**/*.tokens'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token constant">HEADER_COMMENT</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">/**
 * Do not edit directly, this file was auto-generated.
 */\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css_base</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/base/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'base'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">css_themed</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/combined/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables-themed'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>formats<span class="token punctuation">[</span><span class="token string">'css/variables-themed'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>
  dictionary<span class="token punctuation">,</span>
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> semanticTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
    token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'combined'</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> variables <span class="token operator">=</span> semanticTokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> <span class="token punctuation">{</span> name <span class="token punctuation">}</span> <span class="token operator">=</span> token<span class="token punctuation">;</span>
      <span class="token keyword">const</span> description <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$description<span class="token punctuation">;</span>
      <span class="token keyword">const</span> baseVariableName <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">[</span><span class="token string">'$value'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> lightCssVariableName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseVariableName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> darkModeValue <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$mods<span class="token operator">?.</span>dark<span class="token punctuation">;</span>
      <span class="token keyword">const</span> darkCssVariableName <span class="token operator">=</span> darkModeValue
        <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkModeValue
            <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span>
            <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span>
            <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span>
        <span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">;</span>

      <span class="token keyword">if</span> <span class="token punctuation">(</span>darkCssVariableName<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: light-dark(</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lightCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">, </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">);</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lightCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">HEADER_COMMENT</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">:root {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>variables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n}</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="explanation-of-the-script-1" tabindex="-1">Explanation of the Script</h3>
<ol>
<li><strong>light-dark() Function</strong>: The light-dark() function takes two parameters: the light mode variable and the dark mode variable. This allows for a concise way to define styles that adapt based on the user's preference, making it easier to manage changes in themes without duplicating styles.</li>
</ol>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">if</span> <span class="token punctuation">(</span>darkCssVariableName<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: light-dark(</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lightCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">, </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">);</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lightCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<ol start="2">
<li><strong>CSS Variable Generation</strong>: Similar to the previous script, this one extracts semantic tokens and generates CSS variables. The key difference is the use of the light-dark() function, which simplifies the CSS output and enhances readability.</li>
</ol>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> variables <span class="token operator">=</span> semanticTokens
  <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> <span class="token punctuation">{</span> name <span class="token punctuation">}</span> <span class="token operator">=</span> token<span class="token punctuation">;</span>
    <span class="token keyword">const</span> description <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$description<span class="token punctuation">;</span>
    <span class="token keyword">const</span> baseVariableName <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">[</span><span class="token string">'$value'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> lightCssVariableName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseVariableName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> darkModeValue <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$mods<span class="token operator">?.</span>dark<span class="token punctuation">;</span>
    <span class="token keyword">const</span> darkCssVariableName <span class="token operator">=</span> darkModeValue
      <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkModeValue
          <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span>
          <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span>
          <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span>
      <span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">;</span>

    <span class="token comment">// Use light-dark() function for dark mode variables</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>darkCssVariableName<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: light-dark(</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lightCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">, </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">);</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lightCssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="the-generated-css-1" tabindex="-1">The Generated CSS</h3>
<p>After running this script we get a single CSS file for the colours that were in the semantic layer of the design tokens.</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/**
 * Do not edit directly, this file was auto-generated.
 */</span>

<span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-background</span><span class="token punctuation">:</span> <span class="token function">light-dark</span><span class="token punctuation">(</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-base-black<span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-text</span><span class="token punctuation">:</span> <span class="token function">light-dark</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--color-base-black<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-card-background</span><span class="token punctuation">:</span> <span class="token function">light-dark</span><span class="token punctuation">(</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-200<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-800<span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-card-border</span><span class="token punctuation">:</span> <span class="token function">light-dark</span><span class="token punctuation">(</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-600<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-400<span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--button-background-primary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-primary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--button-background-secondary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-secondary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--button-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="wrapping-up" tabindex="-1">Wrapping Up</h2>
<p>In [the first article, we discussed <a href="http://localhost:8080/articles/a-design-tokens-workflow-part-7.html#single-token-file-incorporating-light-and-dark-modes-(one-css-file)">various methods for implementing light and dark modes using design tokens with Style Dictionary</a>. Building on that foundation, here are five effective ways to generate CSS for light and dark modes:</p>
<ol>
<li><strong>Multiple Files for Light and Dark Modes (Two CSS Files)</strong>: Create separate token files for light and dark modes, generating distinct CSS files for each mode. This ensures clear separation and easy management of styles, allowing for straightforward updates and maintenance. <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/07-light-and-dark-mode">View on GitHub</a></li>
<li><strong>Multiple Files for Light and Dark Modes (One CSS File)</strong>: Generate a single CSS file that consolidates styles for both light and dark modes. This method utilises the prefers-color-scheme media feature to apply the appropriate styles based on user preferences, providing a seamless experience. <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/07a-light-and-dark-mode">View on GitHub</a></li>
<li><strong>Single Token File Incorporating Light and Dark Modes (One CSS File)</strong>: Author a single token file that contains both light and dark mode styles. This approach allows for a cohesive view of design tokens and facilitates easier management and updates, generating a single CSS file that includes all necessary styles. <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/07b-light-and-dark-mode">View on GitHub</a></li>
<li><strong>Data Attribute or CSS Class for Dark Mode</strong>: Implement a data attribute or CSS class to enable manual toggling between light and dark modes. This method allows developers to conditionally apply dark mode styles based on the presence of a specific attribute or class in the HTML, enhancing user customization. <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/08-light-and-dark-mode">View on GitHub</a></li>
<li><strong>Using the CSS</strong> light-dark() <strong>Function</strong>: Leverage the CSS light-dark() function to define styles that adapt based on user preferences. This function simplifies the process of switching between light and dark mode styles, allowing developers to specify how styles should adjust without duplicating code.<a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/08a-light-and-dark-mode">View on GitHub</a></li>
</ol>
<p>These methods provide flexibility and adaptability in your design system, ensuring that users have a smooth and personalized experience when interacting with your application.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 7) - Implementing Light and Dark Mode with Style Dictionary</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-7.html"/>
      <updated>2025-03-06T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-7.html</id>
      <content type="html">
        <![CDATA[
        <p>In this tutorial, we will explore how to implement light and dark modes in your design system using design tokens with Style Dictionary. We've previously covered formats, value conversion, extending the design tokens format, and design token layers in earlier tutorials. Today, we will build upon those concepts to effectively manage design tokens for both modes and generate the necessary CSS to ensure a seamless transition.</p>
<h2 id="a-quick-look-at-dark-and-light-mode" tabindex="-1">A Quick Look at Dark and Light Mode</h2>
<p>With the introduction of the ~<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">prefers-color-scheme</a>~ media feature, websites can now provide additional theming options for their visitors by implementing ‘dark mode’ and ‘light mode’. Light mode typically features a bright background with dark text, which is well-suited for use in well-lit environments. Conversely, dark mode employs a dark background with light text, creating a visually comfortable experience for users in low-light conditions. This mode not only reduces eye strain but also enhances readability, making it a popular choice for many applications.
The ability to toggle between these modes has become increasingly important as users seek personalised experiences that cater to their preferences and environments. By leveraging the prefers-color-scheme media query, we can automatically adjust styles based on the user's system settings, ensuring a seamless transition between modes. This adaptability is crucial for modern design systems, as it enhances user satisfaction and accessibility.</p>
<h3 id="the-role-of-design-tokens" tabindex="-1">The Role of Design Tokens</h3>
<p>Design tokens provide a consistent and reusable framework for defining colours, spacing, and other design attributes, facilitating easy management and switching between modes without the need to rewrite styles or adjust individual components. For instance, semantic tokens can be created to specify background and text colours for both light and dark modes, allowing for a seamless transition based on user preferences.
Moreover, design tokens facilitate scalability and maintainability within a design system. By using a single source of truth for colours and styles, teams can ensure that updates to the design are applied uniformly across all components. This consistency is particularly important when implementing light and dark modes, as it helps maintain visual harmony and accessibility across different modes. With design tokens, adjusting the appearance of an entire application becomes a straightforward process, enhancing user experience and satisfaction.</p>
<h2 id="ways-to-author-design-tokens" tabindex="-1">Ways to Author Design Tokens</h2>
<p>In this article, we will explore three methods for creating CSS for light and dark modes using design tokens. Each approach offers unique advantages and can be tailored to fit the needs of your design system.</p>
<ol>
<li><strong>Multiple Files for Light and Dark Modes (Two CSS Files)</strong>: In this method, we will create separate token files for light and dark modes. This setup allows us to generate two distinct CSS files, one for each mode, ensuring clear separation and easy management of styles. Each file will reference its corresponding semantic tokens, making it straightforward to maintain and update styles.</li>
<li><strong>Multiple Files for Light and Dark Modes (One CSS File)</strong>: Similar to the first method, this approach also involves creating separate token files for light and dark modes. However, in this case, we will generate a single CSS file that incorporates styles from both modes. This can be achieved using the prefers-color-scheme media feature to apply the appropriate styles based on user preferences.</li>
<li><strong>Single Token File Incorporating Light and Dark Modes (One CSS File)</strong>: In this approach, we will author a single token file that contains both light and dark mode styles. This method allows for a more cohesive view of the design tokens, facilitating easier management and updates. We will then generate a single CSS file that includes all necessary styles, using a combination of CSS custom properties and media queries to handle the mode switching.
By exploring these three methods, we can demonstrate the flexibility and power of design tokens in managing light and dark modes effectively. Now, let’s dive into the code examples for each approach.</li>
</ol>
<h2 id="getting-started" tabindex="-1">Getting Started</h2>
<p>First, we will look at the multiple JSON files we need to create to generate the appropriate CSS files.</p>
<h3 id="creating-some-design-tokens" tabindex="-1">Creating some Design Tokens</h3>
<p><strong>Base Tokens</strong>
Base tokens are the fundamental building blocks of your design system. They represent the raw, literal values that define colours, spacing, typography, and more. Let's create a short set of base tokens that we can reference to create our light and dark modes.
<strong>tokens/base/colors.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"white"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#FFFFFF"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"black"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#000000"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"gray"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"100"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#F7F7F7"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"200"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#E1E1E1"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"300"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#CFCFCF"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#B3B3B3"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"500"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#A0A0A0"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"600"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#7D7D7D"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"700"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#5A5A5A"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"800"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#3D3D3D"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"900"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#1A1A1A"</span><span class="token punctuation">,</span>
          <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#007BFF"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#6C757D"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>Semantic Tokens</strong>
Now that we've got a simple set of base tokens, we can build on these with semantic tokens, which provide context and meaning. They map to the base tokens and define how these colours should be used in different modes. To effectively manage light and dark modes, we can create separate semantic token files—one for light mode and one for dark mode.
<strong>tokens/semantic/colors.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.white}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Background color for light mode."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.black}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Text color for light mode."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"card"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.200}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Background color for cards in light mode."</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"border"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.600}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Border color for cards in light mode."</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"button"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.primary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Primary button background color in dark mode."</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.secondary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Secondary button background color in dark mode."</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.white}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Text color for buttons in dark mode."</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>tokens/semantic/colors.dark.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.500}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Background color for dark mode."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.white}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Text color for dark mode."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"card"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.800}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Background color for cards in dark mode."</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"border"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.500}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Border color for cards in dark mode."</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>In this structure, we have separate semantic token files for light and dark modes:</p>
<ul>
<li><strong>Background tokens</strong> define the primary background colour for each mode.</li>
<li><strong>Text tokens</strong> specify the colour of the text based on the mode.</li>
<li><strong>Card tokens</strong> provide specific styles for card components, with background and border colours defined for light mode using ⁠{colour.gray.200} and ⁠{colour.gray.600}, and for dark mode using ⁠{colour.gray.800} and ⁠{colour.gray.500}.</li>
<li><strong>Button tokens</strong> specify the background colours for primary and secondary buttons in both modes, ensuring that the appropriate styles are applied based on the selected mode.
This structure, with separate files for light and dark modes, helps maintain clarity and consistency across your design system. It makes it easier to manage colour transitions between modes and ensures a cohesive user experience. |</li>
</ul>
<h2 id="setting-up-style-dictionary" tabindex="-1">Setting Up Style Dictionary</h2>
<p>We need to create a ⁠build.js (or config, or whatever you like to call it) file to set up Style Dictionary to manage these design tokens for light and dark modes. The file will define how the tokens are processed and how the resulting CSS files are generated. Below is the complete code for the ⁠build.js file, followed by an explanation of its key components.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">import</span> <span class="token punctuation">{</span> globSync <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'glob'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> tokenFiles <span class="token operator">=</span> <span class="token function">globSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens/**/*.tokens'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token constant">HEADER_COMMENT</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">/**
 * Do not edit directly, this file was auto-generated.
 */\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css_base</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/base/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'base'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">css_semantic</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/semantic/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
          <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.dark.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables-dark'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
            token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span>
            token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'dark'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
          <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>formats<span class="token punctuation">[</span><span class="token string">'css/variables-dark'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>
  dictionary<span class="token punctuation">,</span>
  options<span class="token punctuation">,</span>
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">{</span> outputReferences <span class="token punctuation">}</span> <span class="token operator">=</span> options<span class="token punctuation">;</span>
  <span class="token keyword">const</span> darkTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>
    <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
      token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'dark'</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> tokens <span class="token operator">=</span> darkTokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> <span class="token punctuation">{</span> name <span class="token punctuation">}</span> <span class="token operator">=</span> token<span class="token punctuation">;</span>
      <span class="token keyword">const</span> baseVariableName <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">[</span><span class="token string">'$value'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Remove curly braces</span>
      <span class="token keyword">const</span> cssVariableName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseVariableName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> description <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$description<span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">HEADER_COMMENT</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">@media (prefers-color-scheme: dark) {\n  :root {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>tokens<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n  }\n}</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now let’s look at a couple of key parts of this JavaScript file:</p>
<h3 id="creating-the-style-dictionary-instance" tabindex="-1">Creating the Style Dictionary Instance</h3>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css_base</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/base/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'base'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">css_semantic</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/semantic/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
          <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.dark.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables-dark'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
            token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span>
            token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'dark'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
          <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>In this section, we create a new instance of ⁠StyleDictionary and configure it to manage our token files. The configuration is divided into two main platforms:</p>
<ol>
<li><strong>css_base</strong>: This platform generates a CSS file (⁠colors.css) for base tokens. The filter ensures that only tokens from the base category are included in this file.</li>
<li><strong>css_semantic</strong>: This platform generates CSS files for semantic tokens. It includes:
<ul>
<li>A <code>⁠colors.cs</code>s file for general semantic tokens. This uses Style Dictionary’s <code>filter</code> so we can only generate tokens from the files that are in the folder ‘semantic’.</li>
<li>A <code>⁠colors.dark.css</code> file specifically for dark mode tokens, using the ⁠variables-dark format. Again this uses Style Dictionary’s <code>filter</code> to look for tokens in the ‘semantic’ folder and also looks for ‘dark’ in the file name. We also use a custom format to compile the tokens to the CSS that we need.</li>
</ul>
</li>
</ol>
<h3 id="registering-the-%E2%81%A0variables-dark-format" tabindex="-1">Registering the ⁠variables-dark Format</h3>
<pre class="language-js"><code class="language-js">StyleDictionary<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>formats<span class="token punctuation">[</span><span class="token string">'css/variables-dark'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>
  dictionary<span class="token punctuation">,</span>
  options<span class="token punctuation">,</span>
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">{</span> outputReferences <span class="token punctuation">}</span> <span class="token operator">=</span> options<span class="token punctuation">;</span>
  <span class="token keyword">const</span> darkTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>
    <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
      token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'dark'</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> tokens <span class="token operator">=</span> darkTokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> <span class="token punctuation">{</span> name <span class="token punctuation">}</span> <span class="token operator">=</span> token<span class="token punctuation">;</span>
      <span class="token keyword">const</span> baseVariableName <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">[</span><span class="token string">'$value'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Remove curly braces</span>
      <span class="token keyword">const</span> cssVariableName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseVariableName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> description <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$description<span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">HEADER_COMMENT</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">@media (prefers-color-scheme: dark) {\n  :root {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>tokens<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n  }\n}</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>This custom format for <code>⁠variables-dark</code> generates CSS custom properties specifically for dark mode. Here’s how it works:</p>
<ul>
<li>The function filters the tokens to include only those that are semantic and marked for dark mode.</li>
<li>It then maps these tokens to create CSS variable declarations, transforming the token names into valid CSS variable names.</li>
<li>The output is wrapped in a media query that applies the styles only when the user prefers dark mode, ensuring that the CSS is conditionally applied based on user settings.</li>
</ul>
<h3 id="building-all-platforms" tabindex="-1">Building All Platforms</h3>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// Build all platforms</span>
myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Finally, this line triggers the build process for all configured platforms, generating the necessary CSS files based on the defined tokens and formats. The console log confirms that the build has completed successfully.</p>
<h2 id="the-generated-css" tabindex="-1">The Generated CSS</h2>
<p>After running the build process, Style Dictionary generates several CSS files based on the defined tokens and formats. Here’s a breakdown of the outputs:
<strong>base/colors.css</strong>
This file contains the base colour tokens defined in your design system. It establishes CSS custom properties (variables) that represent fundamental colours used throughout your application. The output looks like this:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/**
 * Do not edit directly, this file was auto-generated.
 */</span>

<span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-base-white</span><span class="token punctuation">:</span> #ffffff<span class="token punctuation">;</span>
  <span class="token property">--color-base-black</span><span class="token punctuation">:</span> #000000<span class="token punctuation">;</span>
  <span class="token property">--color-base-gray-100</span><span class="token punctuation">:</span> #f7f7f7<span class="token punctuation">;</span>
  <span class="token property">--color-base-gray-200</span><span class="token punctuation">:</span> #e1e1e1<span class="token punctuation">;</span>
  <span class="token property">--color-base-gray-300</span><span class="token punctuation">:</span> #cfcfcf<span class="token punctuation">;</span>
  <span class="token property">--color-base-gray-400</span><span class="token punctuation">:</span> #b3b3b3<span class="token punctuation">;</span>
  <span class="token property">--color-base-gray-500</span><span class="token punctuation">:</span> #a0a0a0<span class="token punctuation">;</span>
  <span class="token property">--color-base-gray-600</span><span class="token punctuation">:</span> #7d7d7d<span class="token punctuation">;</span>
  <span class="token property">--color-base-gray-700</span><span class="token punctuation">:</span> #5a5a5a<span class="token punctuation">;</span>
  <span class="token property">--color-base-gray-800</span><span class="token punctuation">:</span> #3d3d3d<span class="token punctuation">;</span>
  <span class="token property">--color-base-gray-900</span><span class="token punctuation">:</span> #1a1a1a<span class="token punctuation">;</span>
  <span class="token property">--color-base-primary</span><span class="token punctuation">:</span> #007bff<span class="token punctuation">;</span>
  <span class="token property">--color-base-secondary</span><span class="token punctuation">:</span> #6c757d<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>These variables can be used throughout your CSS to maintain consistency in colour usage across different components (this will be the same CSS file for the other two examples also, so I won’t repeat it).
<strong>semantic/colors.css</strong>
This file contains the semantic colour tokens that define how the base colours should be applied in the context of your design system. It specifies colours for light and dark modes, ensuring that the appropriate styles are applied based on the chosen mode. The output includes:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/**
 * Do not edit directly, this file was auto-generated.
 */</span>

<span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
    --color-base-gray-500
  <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Background color for dark mode. */</span>
  <span class="token property">--color-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Text color for dark mode. */</span>
  <span class="token property">--color-card-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
    --color-base-gray-800
  <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Background color for cards in dark mode. */</span>
  <span class="token property">--color-card-border</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
    --color-base-gray-500
  <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Border color for cards in dark mode. */</span>
  <span class="token property">--button-background-primary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
    --color-base-primary
  <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Primary button background color in dark mode. */</span>
  <span class="token property">--button-background-secondary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
    --color-base-secondary
  <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Secondary button background color in dark mode. */</span>
  <span class="token property">--button-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
    --color-base-white
  <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Text color for buttons in dark mode. */</span>
<span class="token punctuation">}</span></code></pre>
<p>This file allows for easy management of colours specific to different components and contexts, ensuring that they adapt correctly to the selected mode.
<strong>semantic/colors.dark.css</strong>
This file is specifically for dark mode and uses the ⁠prefers-color-scheme media query to apply styles conditionally based on user preferences. The output looks like this:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/**
 * Do not edit directly, this file was auto-generated.
 */</span>

<span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
  <span class="token selector">:root</span> <span class="token punctuation">{</span>
    <span class="token property">--color-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
      --color-base-gray-500
    <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Background color for dark mode. */</span>
    <span class="token property">--color-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Text color for dark mode. */</span>
    <span class="token property">--color-card-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
      --color-base-gray-800
    <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Background color for cards in dark mode. */</span>
    <span class="token property">--color-card-border</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
      --color-base-gray-500
    <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Border color for cards in dark mode. */</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>The styles defined here will only be applied when the user’s system is set to dark mode, ensuring that the application responds to user preferences and provides a comfortable viewing experience.</p>
<h2 id="multiple-files-for-light-and-dark-modes-(one-css-file)" tabindex="-1">Multiple Files for Light and Dark Modes (One CSS File)</h2>
<p>In this approach, we will create separate token files for light and dark modes, but instead of generating two distinct CSS files, we will consolidate the styles into a single CSS file. This method allows us to leverage the prefers-color-scheme media feature to apply the appropriate styles based on user preferences seamlessly.</p>
<h3 id="setting-up-the-build-process" tabindex="-1">Setting Up the Build Process</h3>
<p>To implement this method, we will modify our build.js file to include a new format that combines the light and dark mode styles into one CSS file. Below is the complete code for the updated build.js file, followed by an explanation of its key components.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> globSync <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'glob'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> tokenFiles <span class="token operator">=</span> <span class="token function">globSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens/**/*.tokens'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token constant">HEADER_COMMENT</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">/**
* Do not edit directly, this file was auto-generated.
 */\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css_base</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/base/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'base'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">css_semantic</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/semantic/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables-combined'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>formats<span class="token punctuation">[</span><span class="token string">'css/variables-combined'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>
  dictionary<span class="token punctuation">,</span>
  options<span class="token punctuation">,</span>
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">{</span> outputReferences <span class="token punctuation">}</span> <span class="token operator">=</span> options<span class="token punctuation">;</span>
  <span class="token keyword">const</span> semanticTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
    token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> darkTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>
    <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
      token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'dark'</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> semanticVariables <span class="token operator">=</span> semanticTokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> <span class="token punctuation">{</span> name<span class="token punctuation">,</span> comment <span class="token punctuation">}</span> <span class="token operator">=</span> token<span class="token punctuation">;</span>
      <span class="token keyword">const</span> baseVariableName <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">[</span><span class="token string">'$value'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> cssVariableName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseVariableName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>comment <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>comment<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> darkVariables <span class="token operator">=</span> darkTokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> <span class="token punctuation">{</span> name<span class="token punctuation">,</span> comment <span class="token punctuation">}</span> <span class="token operator">=</span> token<span class="token punctuation">;</span>
      <span class="token keyword">const</span> baseVariableName <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">[</span><span class="token string">'$value'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> cssVariableName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseVariableName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>comment <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>comment<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">HEADER_COMMENT</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">:root {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>semanticVariables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkVariables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n  }\n}</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="key-components-of-the-build-process" tabindex="-1">Key Components of the Build Process</h3>
<p><strong>Creating the Style Dictionary Instance</strong></p>
<pre class="language-javascript"><code class="language-javascript"><span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css_base</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/base/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'base'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">css_semantic</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/semantic/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables-combined'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span></code></pre>
<p>In this section, we configure a new instance of StyleDictionary to manage our token files. The configuration includes two main platforms:</p>
<ol>
<li>css_base: This platform generates a CSS file (colors.css) for base tokens, ensuring that only base category tokens are included.</li>
<li>css_semantic: This platform generates a single CSS file for semantic tokens, utilising the new css/variables-combined format.</li>
</ol>
<p><strong>Registering the variables-combined Format</strong></p>
<pre class="language-javascript"><code class="language-javascript">StyleDictionary<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>formats<span class="token punctuation">[</span><span class="token string">'css/variables-combined'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>
  dictionary<span class="token punctuation">,</span>
  options<span class="token punctuation">,</span>
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">{</span> outputReferences <span class="token punctuation">}</span> <span class="token operator">=</span> options<span class="token punctuation">;</span>
  <span class="token keyword">const</span> semanticTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
    token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> darkTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>
    <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
      token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'dark'</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> semanticVariables <span class="token operator">=</span> semanticTokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> <span class="token punctuation">{</span> name<span class="token punctuation">,</span> comment <span class="token punctuation">}</span> <span class="token operator">=</span> token<span class="token punctuation">;</span>
      <span class="token keyword">const</span> baseVariableName <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">[</span><span class="token string">'$value'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> cssVariableName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseVariableName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>comment <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>comment<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> darkVariables <span class="token operator">=</span> darkTokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> <span class="token punctuation">{</span> name<span class="token punctuation">,</span> comment <span class="token punctuation">}</span> <span class="token operator">=</span> token<span class="token punctuation">;</span>
      <span class="token keyword">const</span> baseVariableName <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">[</span><span class="token string">'$value'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> cssVariableName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseVariableName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>comment <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>comment<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">HEADER_COMMENT</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">:root {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>semanticVariables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkVariables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n  }\n}</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>The custom format for variables-combined generates CSS custom properties for both light and dark modes in a single file. Here’s how it works:</p>
<ul>
<li>Token Filtering: The function filters the tokens to include all semantic tokens and those specifically marked for dark mode.</li>
<li>Variable Mapping: It maps the semantic tokens to create CSS variable declarations, transforming token names into valid CSS variable names.</li>
<li>CSS Output: The output is structured to include a root declaration for light mode styles, followed by a media query for dark mode styles.</li>
</ul>
<h3 id="the-generated-css-1" tabindex="-1">The Generated CSS</h3>
<p>After running the build process, Style Dictionary generates a single CSS file that incorporates styles for both light and dark modes. Here’s a breakdown of the output:</p>
<p><strong>semantic/colors.css</strong></p>
<p>This file contains the combined CSS custom properties for light and dark modes, utilising the prefers-color-scheme media query. The output looks like this:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/**
* Do not edit directly, this file was auto-generated.
 */</span>

<span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-500<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-card-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-800<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-card-border</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-500<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--button-background-primary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-primary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--button-background-secondary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-secondary<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--button-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
  <span class="token selector">:root</span> <span class="token punctuation">{</span>
    <span class="token property">--color-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-500<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">--color-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">--color-card-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-800<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">--color-card-border</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-gray-500<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="single-token-file-incorporating-light-and-dark-modes-(one-css-file)" tabindex="-1">Single Token File Incorporating Light and Dark Modes (One CSS File)</h2>
<p>In this approach, we will author a single token file that contains both light and dark mode styles. This method allows for a more cohesive view of the design tokens, facilitating easier management and updates. We will then generate a single CSS file that includes all necessary styles, using a combination of CSS custom properties and media queries to handle the mode switching.</p>
<h3 id="creating-the-design-tokens" tabindex="-1">Creating the Design Tokens</h3>
<p>Here’s an example of how the token file can be structured to incorporate both light and dark mode styles:</p>
<p><strong>tokens/semantic/colors.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.white}"</span><span class="token punctuation">,</span>
      <span class="token property">"$mods"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"dark"</span><span class="token operator">:</span> <span class="token string">"{color.base.black}"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Background color for light mode."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.black}"</span><span class="token punctuation">,</span>
      <span class="token property">"$mods"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"dark"</span><span class="token operator">:</span> <span class="token string">"{color.base.white}"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Text color for light mode."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"card"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.200}"</span><span class="token punctuation">,</span>
        <span class="token property">"$mods"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"dark"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.800}"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Background color for cards in light mode."</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"border"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.600}"</span><span class="token punctuation">,</span>
        <span class="token property">"$mods"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"dark"</span><span class="token operator">:</span> <span class="token string">"{color.base.gray.400}"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Border color for cards in light mode."</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"button"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.primary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Primary button background color in dark mode."</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.secondary}"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
        <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Secondary button background color in dark mode."</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.base.white}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Text color for buttons in dark mode."</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>You will notice in this <code>.tokens</code> file that we have introduce the <code>$mode</code> thing so that we can define additional values for things like dark mode or high contrast mode. This is (for now, possibly) not part of the specification, it comes from <a href="https://github.com/amzn/style-dictionary/issues/1171">this (closed) github issue</a> and I liked it 😊.</p>
<h3 id="setting-up-the-build-process-1" tabindex="-1">Setting Up the Build Process</h3>
<p>To implement this method, we will modify our build.js file to include logic that handles both light and dark mode styles from a single token file. Below is the complete code for the updated build.js file, followed by an explanation of its key components.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> globSync <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'glob'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> tokenFiles <span class="token operator">=</span> <span class="token function">globSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens/**/*.tokens'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token constant">HEADER_COMMENT</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">/**
 * Do not edit directly, this file was auto-generated.
 */\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css_base</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/base/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'base'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">css_semantic</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/combined/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'colors.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables-combined'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>formats<span class="token punctuation">[</span><span class="token string">'css/variables-combined'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>
  dictionary<span class="token punctuation">,</span>
  options<span class="token punctuation">,</span>
<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> semanticTokens <span class="token operator">=</span> dictionary<span class="token punctuation">.</span>allTokens<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
    token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'combined'</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> lightVariables <span class="token operator">=</span> semanticTokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> <span class="token punctuation">{</span> name <span class="token punctuation">}</span> <span class="token operator">=</span> token<span class="token punctuation">;</span>
      <span class="token keyword">const</span> description <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$description<span class="token punctuation">;</span>
      <span class="token keyword">const</span> baseVariableName <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">[</span><span class="token string">'$value'</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> cssVariableName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseVariableName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> darkVariables <span class="token operator">=</span> semanticTokens
    <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> <span class="token punctuation">{</span> name <span class="token punctuation">}</span> <span class="token operator">=</span> token<span class="token punctuation">;</span>
      <span class="token keyword">const</span> description <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$description<span class="token punctuation">;</span>
      <span class="token keyword">const</span> darkModeValue <span class="token operator">=</span> token<span class="token punctuation">.</span>original<span class="token punctuation">.</span>$mods<span class="token operator">?.</span>dark<span class="token punctuation">;</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>darkModeValue<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> baseVariableName <span class="token operator">=</span> darkModeValue<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\{|\}$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">const</span> cssVariableName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseVariableName<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">  --</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cssVariableName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> /* </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> */</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      <span class="token keyword">return</span> <span class="token string">''</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>Boolean<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">HEADER_COMMENT</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">:root {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lightVariables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>darkVariables<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n  }\n}</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="key-components-of-the-build-process-1" tabindex="-1">Key Components of the Build Process</h3>
<p>1. Creating the Style Dictionary Instance:</p>
<ul>
<li>This instance is configured to manage our token files, including a platform for base tokens and a platform for semantic tokens that utilise the new css/variables-combined format.</li>
</ul>
<ol start="2">
<li>Registering the variables-combined Format:</li>
</ol>
<ul>
<li>This custom format generates CSS custom properties for both light and dark modes from a single token file.</li>
<li>It filters the tokens to extract both light mode values and dark mode overrides using the $mods property.</li>
<li>The output is structured to include a root declaration for light mode styles, followed by a media query for dark mode styles.</li>
</ul>
<h3 id="the-generated-css-2" tabindex="-1">The Generated CSS</h3>
<p>After running the build process, Style Dictionary (again) generates a single CSS file that incorporates styles for both light and dark modes. Here’s a breakdown of the output:</p>
<p><strong>semantic/colors.css</strong></p>
<pre class="language-css"><code class="language-css"><span class="token comment">/**
 * Do not edit directly, this file was auto-generated.
 */</span>

<span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
    --color-base-white
  <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Background color for light mode. */</span>
  <span class="token property">--color-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-black<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Text color for light mode. */</span>
  <span class="token property">--color-card-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
    --color-base-gray-200
  <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Background color for cards in light mode. */</span>
  <span class="token property">--color-card-border</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
    --color-base-gray-600
  <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Border color for cards in light mode. */</span>
  <span class="token property">--button-background-primary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
    --color-base-primary
  <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Primary button background color in dark mode. */</span>
  <span class="token property">--button-background-secondary</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
    --color-base-secondary
  <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Secondary button background color in dark mode. */</span>
  <span class="token property">--button-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
    --color-base-white
  <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Text color for buttons in dark mode. */</span>
<span class="token punctuation">}</span>

<span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
  <span class="token selector">:root</span> <span class="token punctuation">{</span>
    <span class="token property">--color-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
      --color-base-black
    <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Background color for dark mode. */</span>
    <span class="token property">--color-text</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-base-white<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Text color for dark mode. */</span>
    <span class="token property">--color-card-background</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
      --color-base-gray-800
    <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Background color for cards in dark mode. */</span>
    <span class="token property">--color-card-border</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>
      --color-base-gray-400
    <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Border color for cards in dark mode. */</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Implementing light and dark modes using design tokens with Style Dictionary enhances user experience and adaptability. This article explored three effective methods for managing design tokens, providing flexibility in your design system.</p>
<ol>
<li><strong>Multiple Files for Light and Dark Modes (Two CSS Files)</strong>: This approach allows for clear separation of styles, generating distinct CSS files for each mode. <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/07-light-and-dark-mode">View on GitHub</a></li>
<li><strong>Multiple Files for Light and Dark Modes (One CSS File)</strong>: By consolidating styles into a single CSS file, this method leverages the ⁠prefers-color-scheme media feature to adapt based on user preferences. <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/07a-light-and-dark-mode">View on GitHub</a></li>
<li><strong>Single Token File Incorporating Light and Dark Modes (One CSS File)</strong>: This cohesive approach simplifies management by using a single token file that includes both light and dark mode styles, facilitating easier updates and maintenance. <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/07b-light-and-dark-mode">View on GitHub</a></li>
</ol>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Sponsorship Opportunities for the Design Systems Newsletter</title>
      <link href="https://www.alwaystwisted.com/articles/sponsorship-opportunities-for-the-design-systems-newsletter.html"/>
      <updated>2025-02-10T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/sponsorship-opportunities-for-the-design-systems-newsletter.html</id>
      <content type="html">
        <![CDATA[
        <p>I’m thrilled to announce that the <a href="https://news.design.systems"><strong>Design Systems Newsletter</strong></a> is now open for sponsorship!</p>
<p>With over <strong>3,700 subscribers</strong> and an impressive average open rate of <strong>54%</strong> and click-through rate of <strong>16%</strong>, this newsletter reaches a highly engaged audience that values quality content.</p>
<h3 id="why-sponsorship%3F" tabindex="-1">Why Sponsorship?</h3>
<p>As the newsletter continues to grow, sponsorship will help cover costs and support the time dedicated to curating the best articles and resources for our readers.</p>
<p>I’m looking for sponsorship from companies and folks that work in and around the <strong>Design Systems</strong> space or have products that could support the designers or developers who work on design systems.</p>
<h3 id="sponsorship-details" tabindex="-1">Sponsorship Details</h3>
<ul>
<li><strong>Cost</strong>: £200 per issue</li>
<li><strong>Frequency</strong>: Issues may be sporadic, with a maximum frequency of weekly releases. I prioritise sharing only the most valuable content, so newsletters will be sent out when there’s enough to share.</li>
<li><strong>Payment Terms</strong>: &quot;Pay before you play.&quot; Sponsorship fees are required upfront prior to the newsletter being sent out.</li>
</ul>
<h3 id="advertisement-placement" tabindex="-1">Advertisement Placement</h3>
<ul>
<li>The advertisement will be <strong>text-only</strong> and placed at the end of the newsletter.</li>
<li>Additionally, it will also be featured on the <strong>archive site</strong> as part of the newsletter, providing extended visibility for your brand.</li>
</ul>
<h3 id="about-me" tabindex="-1">About Me</h3>
<p>I am also seeking work opportunities as a <strong>front-end developer</strong> and a dedicated <strong>design systems advocate</strong>. With over <strong>12 years of experience</strong>, I have helped organisations and teams create and maintain effective design systems, and I enjoy teaching advanced <strong>Sass</strong> and <strong>CSS techniques</strong>.</p>
<p>If you’re interested in sponsoring the Design Systems newsletter or if you have potential work opportunities, please feel free to <a href="http://www.alwaystwisted.com/contact">reach out</a>. I look forward to collaborating and creating impactful content together!</p>
<p>Alternatively, you can help me by <a href="https://buymeacoffee.com/sturobson">buying me a coffee</a>.</p>
<p>🙏🖤</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Adding Random Content Using Eleventy</title>
      <link href="https://www.alwaystwisted.com/articles/random-content-using-eleventy.html"/>
      <updated>2024-12-13T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/random-content-using-eleventy.html</id>
      <content type="html">
        <![CDATA[
        <p>Since I've had a rejuvenation in writing again after I finally pushed this sites redesign live I have had a link component at the bottom of every article stating that I have availabilty for new client work.</p>
<p>Fast forward ~9 weeks from the website going live and 15 articles later I thought it would be neat to have a beter 'call out' at the bottom of my articles. A &quot;question and answer&quot; that could show potential cliens how I can help them. Because I have ended up, and will carry on, writing on a variety of topics I thought it would be even cooler if I had targetted &quot;Q and As&quot; depending on the topic of the article.</p>
<p>What I cam up with was 24 different questions and answers for Design Systems, CSS, Design Tokens and Front-End Development. The idea would be that every time my site gets rebuild each article page would have one of these different &quot;Q and As&quot; generated at random.</p>
<p>Using Eleventy I have distilled that code to help you add a random horror movie quote to your website pages (using Eleventy).</p>
<img alt="A purple box with text: Need to integrate design tokens into your build tools or component libraries? I'll integrate tokens into your build process and component libraries for smooth workflows. With a lighter purple button that has text of 'get in touch' to the right." src="/images/articles/QandA.png">
<h2 id="what-we'll-build" tabindex="-1">What We'll Build</h2>
<p>For this article we will build a component that:</p>
<ul>
<li>Displays a random film quote when the site is built.</li>
<li>Randomises the quote every time the site is rebuilt.</li>
<li>Uses a simple JSON file for storing quotes, making it easy to update and expand.</li>
</ul>
<h2 id="setting-up-the-quotes" tabindex="-1">Setting Up The Quotes</h2>
<p>First, we will need to create a <code>.json</code> file to store our film quotes. We can add a new file (<code>film-quotes.json</code>) in the <code>_data</code> folder of your Eleventy project and populate it with your favourite film qoutes. I'm a big horror fan, so for me it would look somehing like this:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"quotes"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"They're here."</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"Poltergeist"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"Do you like scary movies?"</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"Scream"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"Whatever you do, don’t fall asleep."</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"A Nightmare on Elm Street"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"Be afraid… Be very afraid."</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"The Fly"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"It’s alive! It’s alive!"</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"Frankenstein"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"Here’s Johnny!"</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"The Shining"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"We all go a little mad sometimes."</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"Psycho"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"I see dead people."</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"The Sixth Sense"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"You’re gonna need a bigger boat."</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"Jaws"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"In space, no one can hear you scream."</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"Alien"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">]</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="creating-the-randomiser" tabindex="-1">Creating The Randomiser</h2>
<p>Next, we’ll create a shortcode to fetch a random quote from our JSON file.</p>
<p>This shortcode will pick a single random quote during the build process, ensuring that the selected quote changes only when the site is rebuilt. The setup is simple, using the Math.random() function to select a quote from the list.</p>
<p>Add the following code to your .eleventy.js file:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> path <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">eleventyConfig</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// Load film quotes</span>
  <span class="token keyword">const</span> filmQuotes <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./website/_data/film-quotes.json'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Register random film quote shortcode</span>
  config<span class="token punctuation">.</span><span class="token function">addShortcode</span><span class="token punctuation">(</span><span class="token string">'randomFilmQuote'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> randomIndex <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> filmQuotes<span class="token punctuation">.</span>quotes<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> randomQuote <span class="token operator">=</span> filmQuotes<span class="token punctuation">.</span>quotes<span class="token punctuation">[</span>randomIndex<span class="token punctuation">]</span><span class="token punctuation">;</span>

    <span class="token comment">// Return the quote directly</span>
    <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
    &lt;blockquote>
      </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>randomQuote<span class="token punctuation">.</span>quote<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">
      &lt;cite>— </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>randomQuote<span class="token punctuation">.</span>film<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/cite>
    &lt;/blockquote>
    </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h2 id="using-the-shortcode-in-your-template" tabindex="-1">Using The Shortcode In Your Template</h2>
<p>In your Nunjucks template (or any Eleventy compatible emplate), use the <code>randomFilmQuote</code> shortcode wherever you want the quote to appear.</p>
<pre class="language-nunjucks"><code class="language-nunjucks"><span class="token operator">&lt;</span><span class="token variable">div</span> <span class="token variable">class</span><span class="token operator">=</span><span class="token string">"quote-of-the-day"</span><span class="token operator">></span>
  <span class="token operator">&lt;</span><span class="token variable">h2</span><span class="token operator">></span><span class="token variable">Film</span> <span class="token variable">Quote</span> <span class="token variable">of</span> <span class="token variable">the</span> <span class="token variable">Day</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token variable">h2</span><span class="token operator">></span>
  <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token variable">randomFilmQuote</span> <span class="token operator">%</span><span class="token punctuation">}</span>
<span class="token operator">&lt;</span><span class="token operator">/</span><span class="token variable">div</span><span class="token operator">></span></code></pre>
<h2 id="updating-the-randomiser-to-use-a-nunjucks-component" tabindex="-1">Updating the Randomiser to Use a Nunjucks Component</h2>
<p>I don't know about you, but I prefer to have things as 'close to the metal' as possible, so let's pull the HTML generated in the shortcode out and put it into a Nunjucks component that can be called instead.</p>
<h3 id="moving-the-html-into-a-nunjucks-component" tabindex="-1">Moving the HTML into a Nunjucks Component</h3>
<p>Create a Nunjucks component template in your project. Let’s call it <code>film-quotes.njk</code>, and place it in your components folder (<code>src/incldues/components/film[quotes.njk</code>):</p>
<pre class="language-nunjucks"><code class="language-nunjucks"><span class="token delimiter punctuation">{%</span> <span class="token tag keyword">set</span> <span class="token variable">randomQuote</span> <span class="token operator">=</span> <span class="token function">randomFilmQuote</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">%</span><span class="token punctuation">}</span>

<span class="token operator">&lt;</span><span class="token variable">blockquote</span><span class="token operator">></span>
  <span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token variable">randomQuote</span><span class="token punctuation">.</span><span class="token variable">quote</span> <span class="token punctuation">}</span><span class="token punctuation">}</span>
  <span class="token operator">&lt;</span><span class="token variable">cite</span><span class="token operator">></span>— <span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token variable">randomQuote</span><span class="token punctuation">.</span><span class="token variable">film</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token variable">cite</span><span class="token operator">></span>
<span class="token operator">&lt;</span><span class="token operator">/</span><span class="token variable">blockquote</span><span class="token operator">></span></code></pre>
<h3 id="updating-the-shortcode-to-use-the-component" tabindex="-1">Updating the Shortcode to Use The Component</h3>
<p>As we're removing the HTML from he shortcode we will need to update it so that it can render the Nunjucks component instead of directly generating the HTML. To do this, we can use Eleventy's built-in Nunucks rendering</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> path <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">config</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// Load film quotes</span>
  <span class="token keyword">const</span> filmQuotes <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./website/_data/film-quotes.json'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Register random film quote shortcode</span>
  config<span class="token punctuation">.</span><span class="token function">addShortcode</span><span class="token punctuation">(</span><span class="token string">'randomFilmQuote'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> randomIndex <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> filmQuotes<span class="token punctuation">.</span>quotes<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> filmQuotes<span class="token punctuation">.</span>quotes<span class="token punctuation">[</span>randomIndex<span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Expose the shortcode for Nunjucks</span>
  config<span class="token punctuation">.</span><span class="token function">addNunjucksGlobal</span><span class="token punctuation">(</span><span class="token string">'randomFilmQuote'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> randomIndex <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> filmQuotes<span class="token punctuation">.</span>quotes<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> filmQuotes<span class="token punctuation">.</span>quotes<span class="token punctuation">[</span>randomIndex<span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h3 id="updating-the-template-to-use-the-shortcode" tabindex="-1">Updating the Template to Use The Shortcode</h3>
<p>With this update to the Shortcode we don't need to make any changes to our template</p>
<pre class="language-nunjucks"><code class="language-nunjucks"><span class="token operator">&lt;</span><span class="token variable">div</span> <span class="token variable">class</span><span class="token operator">=</span><span class="token string">"quote-of-the-day"</span><span class="token operator">></span>
  <span class="token operator">&lt;</span><span class="token variable">h2</span><span class="token operator">></span><span class="token variable">Film</span> <span class="token variable">Quote</span> <span class="token variable">of</span> <span class="token variable">the</span> <span class="token variable">Day</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token variable">h2</span><span class="token operator">></span>
  <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token variable">randomFilmQuote</span> <span class="token operator">%</span><span class="token punctuation">}</span>
<span class="token operator">&lt;</span><span class="token operator">/</span><span class="token variable">div</span><span class="token operator">></span></code></pre>
<h2 id="creating-choices-with-sets-of-quotes" tabindex="-1">Creating choices With Sets Of Quotes</h2>
<p>With my sites component I mentioned I have 4 categories that can either be chosen per page or per component instance or left to be completely random. Let's see what we need to do to that if we have quotes from horror movies and sci-fi movies.</p>
<h3 id="updating-the-.json" tabindex="-1">Updating the .json</h3>
<p>Let's split the quotes out into two categories (I've shortened the <code>.json</code> for this example):</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"horror"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"They're here."</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"Poltergeist"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"Do you like scary movies?"</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"Scream"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token property">"scifi"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"In space, no one can hear you scream."</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"Alien"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token property">"quote"</span><span class="token operator">:</span> <span class="token string">"The Force will be with you. Always."</span><span class="token punctuation">,</span>
      <span class="token property">"film"</span><span class="token operator">:</span> <span class="token string">"Star Wars"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">]</span>
<span class="token punctuation">}</span></code></pre>
<p>Now we need to add a bunch more JavaScript to our shortcode to allow for the multiple categories and the option to choose which category or not:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> path <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">config</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// Load film quotes</span>
  <span class="token keyword">const</span> filmQuotes <span class="token operator">=</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>
    fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'website/_data/film-quotes.json'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Register random film quote shortcode</span>
  config<span class="token punctuation">.</span><span class="token function">addShortcode</span><span class="token punctuation">(</span><span class="token string">'randomFilmQuote'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">category <span class="token operator">=</span> <span class="token keyword">null</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> selectedQuotes<span class="token punctuation">;</span>

    <span class="token keyword">if</span> <span class="token punctuation">(</span>category<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      selectedQuotes <span class="token operator">=</span> filmQuotes<span class="token punctuation">[</span>category<span class="token punctuation">]</span><span class="token punctuation">;</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>selectedQuotes<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span>
          <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Category '</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>category<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">' not found. Available categories: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>
            filmQuotes
          <span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">', '</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span>
        <span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      <span class="token comment">// Use all quotes if no category specified</span>
      selectedQuotes <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">values</span><span class="token punctuation">(</span>filmQuotes<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">flat</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">const</span> randomIndex <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> selectedQuotes<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> selectedQuotes<span class="token punctuation">[</span>randomIndex<span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Expose the shortcode for Nunjucks</span>
  config<span class="token punctuation">.</span><span class="token function">addNunjucksGlobal</span><span class="token punctuation">(</span><span class="token string">'randomFilmQuote'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">category <span class="token operator">=</span> <span class="token keyword">null</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> selectedQuotes<span class="token punctuation">;</span>

    <span class="token keyword">if</span> <span class="token punctuation">(</span>category<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      selectedQuotes <span class="token operator">=</span> filmQuotes<span class="token punctuation">[</span>category<span class="token punctuation">]</span><span class="token punctuation">;</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>selectedQuotes<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span>
          <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Category '</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>category<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">' not found. Available categories: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>
            filmQuotes
          <span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">', '</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span>
        <span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      selectedQuotes <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">values</span><span class="token punctuation">(</span>filmQuotes<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">flat</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">const</span> randomIndex <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> selectedQuotes<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> selectedQuotes<span class="token punctuation">[</span>randomIndex<span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>Now we can add an <code>if</code> statement to our nunjucks to see if there is a category in the frontmatter</p>
<pre class="language-nunjucks"><code class="language-nunjucks"><span class="token delimiter punctuation">{%</span> <span class="token tag keyword">if</span> <span class="token variable">category</span> <span class="token operator">%</span><span class="token punctuation">}</span>
  <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token variable">set</span> <span class="token variable">randomQuote</span> <span class="token operator">=</span> <span class="token function">randomFilmQuote</span><span class="token punctuation">(</span><span class="token variable">category</span><span class="token punctuation">)</span> <span class="token operator">%</span><span class="token punctuation">}</span>
<span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">else</span> <span class="token operator">%</span><span class="token punctuation">}</span>
  <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token variable">set</span> <span class="token variable">randomQuote</span> <span class="token operator">=</span> <span class="token function">randomFilmQuote</span><span class="token punctuation">(</span><span class="token variable">null</span><span class="token punctuation">)</span> <span class="token operator">%</span><span class="token punctuation">}</span>
<span class="token punctuation">{</span><span class="token operator">%</span> <span class="token variable">endif</span> <span class="token operator">%</span><span class="token punctuation">}</span>

<span class="token operator">&lt;</span><span class="token variable">blockquote</span> <span class="token variable">class</span><span class="token operator">=</span><span class="token string">"film-quote"</span><span class="token operator">></span>
  <span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token variable">randomQuote</span><span class="token punctuation">.</span><span class="token variable">quote</span> <span class="token punctuation">}</span><span class="token punctuation">}</span>
  <span class="token operator">&lt;</span><span class="token variable">cite</span><span class="token operator">></span>— <span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token variable">randomQuote</span><span class="token punctuation">.</span><span class="token variable">film</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token variable">cite</span><span class="token operator">></span>
<span class="token operator">&lt;</span><span class="token operator">/</span><span class="token variable">blockquote</span><span class="token operator">></span></code></pre>
<p>If we set the <code>category</code> in the frontmatter of the page it will then pick a random quote from that category</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token punctuation">---</span>
<span class="token key atrule">quoteCategory</span><span class="token punctuation">:</span> <span class="token string">'scifi'</span>
<span class="token punctuation">---</span></code></pre>
<img alt="a light orange box with a heading of Film Quote of the Day - The Force will be with you. Always. - Star Wars" src="/images/articles/FilmQuote.png">
<p>The approach we've looked at in this article could be applied to a wide variety of uses cases beyond film quotes, or questions and answers. You could use it to display a random testimonial, rotate customer feedback on your landing pages. Alternatively you could implement it to showcase random facts or trivia. Or, like I do, you could use this to power targeted calls to action, displaying relevant messages to specific blogposts.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 6) - Layers, referencing tokens in Style Dictionary</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-6.html"/>
      <updated>2024-12-12T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-6.html</id>
      <content type="html">
        <![CDATA[
        <p>In previous tutorials, we explored how to create and generate design tokens using Style Dictionary. Now, we'll build upon that foundation by setting up token layers in Style Dictionary, showing how to reference tokens across layers and generate outputs for better usability.</p>
<h2 id="a-brief-explanation-of-design-tokens-layers" tabindex="-1">A brief explanation of Design Tokens layers</h2>
<p>Design Token layers can be essential for creating a scalable and maintainable design system. They can help separate raw values from their contextual meanings. In separating tokens into different layers, such as base, semantic, and component tokens, we can better organise their purposes and usage while ensuring the system remains flexible and future-proof.</p>
<p>The most common layers used for Design Tokens in a Design System include <strong>base</strong>, <strong>semantic</strong>, and <strong>component</strong> tokens, each serve a unique role in your workflow.</p>
<ul>
<li><strong>Base Tokens</strong>: These are the raw, literal values, such as <code>#bada55</code> for a green colour or <code>1rem</code> for spacing. They form the foundation of your design system, with descriptive names that reflect their physical properties (e.g., <code>color-green-400</code>, <code>spacing-small</code>).</li>
<li><strong>Semantic Tokens</strong>: These tokens provide context and meaning to the base tokens. For example, <code>--note-color</code> might reference the base token <code>--color-green-400</code>. Semantic tokens abstract intent, making them easier to use and apply consistently across a design system.</li>
<li><strong>Component Tokens</strong>: These tokens define values specific to individual components, such as <code>--button-primary-bg</code> for a button’s background colour. Component tokens build upon semantic tokens to tailor the design system for particular use cases. While they play a crucial role in token workflows, we won’t explore them in detail today, focusing instead on base and semantic layers.</li>
</ul>
<p>Separating tokens into layers provides flexibility and scalability. Semantic tokens allow users to work with meaningful names while base tokens remain stable and reusable. This separation can also support theming, where adjusting base tokens can create design variations without changes to semantic tokens.</p>
<p>While “base” and “semantic” are widely used terms, some teams prefer alternatives like “literal” or “raw” for base tokens and “contextual” for semantic tokens.</p>
<p>Regardless of your chosen terminology, maintaining clarity and consistency within your system is key.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>For more details on Design Tokens layers you can read <a href="https://medium.com/eightshapes-llc/naming-tokens-in-design-systems-9e86c7444676">Naming Tokens in Design Systems</a> from Nathan Curtis and <a href="https://www.smashingmagazine.com/2024/05/naming-best-practices/%22">Best Practices For Naming Design Tokens, Components And Variables</a> from Cosima on Smashing Magazine</p>
</div>
<h2 id="setting-up-style-dictionary-for-token-layers" tabindex="-1">Setting Up Style Dictionary for Token Layers</h2>
<p>To effectively separate token layers using Style Dictionary, we will organise our files and folders to reflect the layered structure we are aiming for. This setup allows us to maintain a clear distinction between the raw values and their contextual meanings while also enabling outputs that can meet various design and development goals.</p>
<h3 id="configuring-style-dictionary-to-separate-base-and-semantic-tokens" tabindex="-1">Configuring Style Dictionary to Separate Base and Semantic Tokens</h3>
<p>The first step to setting up token layers is to organise the token files into distinct folders for base and semantic tokens. This should make it easier to manage each layer independently.</p>
<p>Here’s an example of a simple folder structure:</p>
<pre><code>tokens/
    ├── base/
    │   ├── colors.tokens
    │   ├── spacing.tokens
    └── semantic/
        ├── colors.tokens
        ├── padding.tokens
</code></pre>
<p>To generate separate outputs for these layers, we’ll configure Style Dictionary to filter tokens by folder and output them to distinct files or directories. Below is an example configuration using Style Dictionary:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token comment">// Configure Style Dictionary</span>
<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'src/tokens/**/*.tokens'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token comment">// Output file for base tokens</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'base/tokens.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token comment">// Filter for base tokens</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'base'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token comment">// Output file for semantic tokens</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'semantic/tokens.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token comment">// Filter for semantic tokens</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Build all platforms</span>
myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This configuration will build two separate outputs, one for the base tokens (<code>build/base/tokens.css</code>) and another for the semantic tokens (<code>build/semantic/tokens.css</code>).</p>
<h3 id="referencing-base-tokens-in-semantic-tokens" tabindex="-1">Referencing Base Tokens in Semantic Tokens</h3>
<p>Design Token layers can build upon other layers by referencing them in their definitions. Style Dictionary makes this simple with its {tokenPath} syntax. For example:</p>
<p><strong>Base Tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"red"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ff0000"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>Semantic Tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"warning"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.red.400}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Using the configuration above this will resolve the <code>{color-warning}</code> in the semantic tokens to a hardcoded value:</p>
<p><strong>Base Tokens CSS</strong></p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-red-400</span><span class="token punctuation">:</span> #ff0000<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>Semantic Tokens CSS</strong></p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-warning</span><span class="token punctuation">:</span> #ff0000<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>By default, Style Dictionary replaces the <code>{color.red.400}</code> reference with its resolved value <code>(#ff0000)</code>. This behaviour is intentional and ensures the output works even if references are not supported in the target environment.</p>
<h2 id="retaining-variable-references-in-outputs" tabindex="-1">Retaining Variable References in Outputs</h2>
<p>If you want the semantic tokens to reference base tokens as CSS custom properties or Sass variables (for example), you need to enable the <code>outputReferences</code> option in your Style Dictionary configuration:</p>
<p>The updated configuration file now looks like this:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'src/tokens/**/*.tokens'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'base/tokens.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'base'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'semantic/tokens.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
          <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>With this updated configuration, the output will retain references:</p>
<p><strong>Base Tokens CSS</strong></p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-red-400</span><span class="token punctuation">:</span> #ff0000<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>Semantic Tokens CSS</strong></p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-warning</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-red-400<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="variable-references-vs.-hardcoded-values" tabindex="-1">Variable References vs. Hardcoded Values</h3>
<p>When generating semantic tokens, you can decide whether to reference base tokens as variables or use hard coded values:</p>
<p><strong>Variable References</strong> (<code>--warning-color: var(--color-red-400);</code> )</p>
<p>Referencing base tokens as variables ensures that updates to base tokens cascade automatically to semantic tokens. This is particularly useful for theming or maintaining consistency across large systems. However, it requires including both base and semantic tokens in the final output, which can increase file size and dependencies.</p>
<p><strong>Hardcoded Values</strong> (<code>--warning-color: #ff0000</code>)</p>
<p>Hardcoding values in semantic tokens improves portability, as semantic tokens can be used independently of base tokens. However, it sacrifices flexibility, requiring updates in multiple places if a base value changes.</p>
<p>Choosing between these approaches depends on the goals of your design system. Variable references are ideal for systems where flexibility and theming are priorities, while hardcoded values can work better in simpler setups or when portability is key.</p>
<h2 id="generating-separate-files-with-layered-outputs" tabindex="-1">Generating Separate Files with Layered Outputs</h2>
<p>To effectively manage layered Design Tokens, I think it's essential to generate separate output files that maintain the folder structure and filenames of the source tokens. This approach ensures that each file remains modular and easy to integrate into your workflows. Using Style Dictionary, we can achieve this while maintaining proper references in semantic tokens.</p>
<p>To combine the Design Token Layers with <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-5">separate file outputs from the fifth article</a> we need to change our configuration file a bit.</p>
<p>The code for this part of the series <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/06-creating-layers">can be found here</a></p>
<p>First, we're going to make use of the <code>glob</code> npm package to easily find all the <code>.tokens</code> files in the folder.</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> glob</code></pre>
<p>We then need to create an array that processes each <code>.tokens</code> file to generate corresponding <code>.css</code> outputs, preserving the folder structure, filtering tokens by file, and enabling references for semantic tokens.</p>
<p>If you prefer hardcoded values and want to reduce the number of files, simply omit the <code>outputReferences</code> option from the configuration.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> globSync <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'glob'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> path <span class="token keyword">from</span> <span class="token string">'path'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> tokenFiles <span class="token operator">=</span> <span class="token function">globSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens/**/*.tokens'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">file</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> relativeFilePath <span class="token operator">=</span> path
          <span class="token punctuation">.</span><span class="token function">relative</span><span class="token punctuation">(</span><span class="token string">'src/tokens'</span><span class="token punctuation">,</span> file<span class="token punctuation">)</span>
          <span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\\</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'/'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> relativeFilePath<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token string">'.tokens'</span><span class="token punctuation">,</span> <span class="token string">'.css'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">endsWith</span><span class="token punctuation">(</span>relativeFilePath<span class="token punctuation">)</span><span class="token punctuation">,</span>
          <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">outputReferences</span><span class="token operator">:</span> file<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">'semantic'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This configuration generates <code>.css</code> files for each <code>.tokens</code> file found in the src/tokens directory, preserving the folder structure and applying specific logic for base and semantic tokens:</p>
<h3 id="directory-structure" tabindex="-1">Directory Structure</h3>
<p>For a <code>src/tokens/</code> directory structured like this:</p>
<pre><code>src/tokens/
├── base/
│   ├── color.tokens
│   ├── spacing.tokens
├── semantic/
│   ├── color.tokens
│   ├── typography.tokens
</code></pre>
<p>The output directory will look like this:</p>
<pre><code>build/css/
├── base/
│   ├── color.css
│   ├── spacing.css
├── semantic/
│   ├── color.css
│   ├── typography.css
</code></pre>
<h3 id="base-token-output" tabindex="-1">Base Token Output</h3>
<p>Tokens in base files output hard coded values without references. For example:</p>
<p><strong><code>tokens/base/color.tokens</code></strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"red"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"400"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ff0000"</span><span class="token punctuation">,</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong><code>build/base/color.css</code></strong></p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-red-400</span><span class="token punctuation">:</span> #ff0000<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="semantic-token-output" tabindex="-1">Semantic Token Output</h3>
<p>Tokens in semantic files reference base tokens using <code>var(...)</code>. For example:
<strong><code>tokens/semantic/color.tokens</code></strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"warning"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"{color.red.400}"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong><code>build/semantic/color.css</code></strong></p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-warning</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-red-400<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="a-note-on-warnings" tabindex="-1">A Note on Warnings</h3>
<p>Using this approach will likely have Style Dictionary in a bit of a spin and provide a <strong>warning</strong> in the terminal when the code is generated.</p>
<pre class="language-bash"><code class="language-bash">⚠️ build/css/semantic/padding.css
While building semantic/padding.css, filtered out token references were found<span class="token punctuation">;</span> output may be unexpected. Ignore this warning <span class="token keyword">if</span> intentional.</code></pre>
<p>The warning indicates that some tokens in the output reference other tokens that were filtered out, potentially leading to broken references in the generated file. This happens because <code>outputReferences: true</code> tries to preserve variable references (<code>var(--token-name)</code>), but the referenced tokens are not included in the same output file.</p>
<p>I think you can safely ignore the warning if you’ve confirmed that the referenced tokens are included in other output files used alongside the semantic files, and the output meets your expectations.</p>
<p>However, if the semantic files need to function independently, you should either address the warning by including all necessary references in the same file or remove outputReferences: true to default to hardcoded values.</p>
<h2 id="component-tokens" tabindex="-1">Component Tokens</h2>
<p>While this article focuses on two layers of Design Tokens, it’s worth briefly introducing <strong>component tokens</strong> as the next layer in a Design Token hierarchy. Component tokens are values tailored to specific elements and components, such as buttons, cards, or headings, and are often built upon semantic tokens to ensure consistency with the broader Design System.</p>
<p>As an example, a button's background colour might use a semantic token like <code>--primary-color</code> (if you set <code>outputPreferences: true</code> like above):</p>
<pre class="language-css"><code class="language-css"><span class="token property">--button-primary-bg</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--primary-color<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Component tokens can provide flexibility for customisation while maintaining alignment with the Design System’s semantics. They enable teams to define granular, component-specific styles without duplicating design intent across multiple components.</p>
<p>This approach also makes it easier to manage component-level theming and variations. For instance, a <code>--button-secondary-bg</code> token could reference the same semantic base but apply a slightly different tint for differentiation.</p>
<p>We’ll explore the role of component tokens, their setup, and practical applications in a future article, where they’ll be integrated as part of a cohesive Design Tokens workflow.</p>
<p>Layering Design Tokens with Style Dictionary is a practical way to create a clear and scalable Design System. By splitting tokens into layers like base and semantic, you can define them more clearly, adapt easily for theming, and make life simpler for design and development teams.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Quick and Dirty Colour Palettes using color-mix()</title>
      <link href="https://www.alwaystwisted.com/articles/quick-and-dirty-colour-palettes-using-color-mix.html"/>
      <updated>2024-12-09T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/quick-and-dirty-colour-palettes-using-color-mix.html</id>
      <content type="html">
        <![CDATA[
        <p>When I first started tinkering on the idea of a redesign of this site in ~2019 (yeah, it took that long) I started prototyping the layout (which changed) and other aspects of the site (theming) using CodePen.</p>
<p>To make things easier with my idea for theming (having lighter and darker variations of the primary colour for the background, foreground, etc.) I looked at using the (then) relatively new CSS feature <code>color-mix()</code>.</p>
<h2 id="what-is-color-mix()%3F" tabindex="-1">What is color-mix()?</h2>
<p>Simply put, rhe <code>color-mix()</code> CSS function lets you blend two colours together. You also have the option to choose how much of each colour you want to mix and pick the colour space it works in, like <code>srgb</code>, or <code>display-p3</code>.</p>
<p>This makes it great for creating simple colour palettes with:</p>
<ul>
<li><strong>tints</strong>: adding a bit of white to lighten a colour.</li>
<li><strong>shades</strong>: mixing in black to darken it.</li>
<li><strong>opacity</strong>: blend a colour with the <code>transparent</code> keyword to allow the background to bleed through.</li>
</ul>
<p>The syntax for <code>color-mix</code> is quite simple:</p>
<pre class="language-css"><code class="language-css"><span class="token function">color-mix</span><span class="token punctuation">(</span>in &lt;color-space><span class="token punctuation">,</span> &lt;color-1> &lt;percentage-1><span class="token punctuation">,</span> &lt;color-2> &lt;percentage-2><span class="token punctuation">)</span></code></pre>
<p>Here's what each part means:</p>
<ol>
<li><code>&lt;color-space&gt;</code> specifies the colours space to do the blending in, common options are: <code>srgb</code> and <code>display-p3</code>.</li>
<li><code>&lt;color-1&gt;</code> is the first colour in the mix, this could be a custom property. a named colour, or a colour code.</li>
<li><code>&lt;percentage-1&gt;</code> denotes the proportion of the first colour to be blended.</li>
<li><code>&lt;color-2&gt;</code> is the second colour that is to be blended.</li>
<li><code>&lt;percentage-2&gt;</code> would be how much of the second colour is mixed with the first.</li>
</ol>
<p>You can also omit one of the percentages, the remaining percentage is automatically calculated:</p>
<pre class="language-css"><code class="language-css"><span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>in srgb<span class="token punctuation">,</span> #bada55 70%<span class="token punctuation">,</span> #c0ffee 30%<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Can be shortened to either:</p>
<pre class="language-css"><code class="language-css"><span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>in srgb<span class="token punctuation">,</span> #bada55 70%<span class="token punctuation">,</span> #c0ffee<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Or:</p>
<pre class="language-css"><code class="language-css"><span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>in srgb<span class="token punctuation">,</span> #bada55<span class="token punctuation">,</span> #c0ffee 30%<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p><a href="https://bsky.app/profile/nerdy.dev">Adam</a> explains how <code>color-mix()</code> works and more in <a href="https://developer.chrome.com/docs/css-ui/css-color-mix">this Chrome Developers blogpost</a>.</p>
</div>
<h2 id="creating-simple-colour-palettes" tabindex="-1">Creating Simple Colour Palettes</h2>
<p>Let's start with a primary colour and black and white as CSS custom properties and generate some tints and shades using <code>color-mix()</code>.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-black</span><span class="token punctuation">:</span> #000000<span class="token punctuation">;</span>
  <span class="token property">--color-white</span><span class="token punctuation">:</span> #ffffff<span class="token punctuation">;</span>
  <span class="token property">--color-primary</span><span class="token punctuation">:</span> #bada55<span class="token punctuation">;</span>

  <span class="token comment">/* tints */</span>
  <span class="token property">--color-primary--tint-10</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> 10%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--tint-20</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> 20%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">/* Shades */</span>
  <span class="token property">--color-primary--shade-10</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-black<span class="token punctuation">)</span> 10%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--shade-20</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-black<span class="token punctuation">)</span> 20%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>With just a few lines, you’ve got lighter and darker variations that you can reuse for things like hover states, text, or borders.</p>
<h2 id="adding-opacity-variants" tabindex="-1">Adding Opacity Variants</h2>
<p>If you need semi-transparent colours, <code>color-mix()</code> works just as well. By blending with <code>transparent</code>, you can create a range of opacity levels:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-primary</span><span class="token punctuation">:</span> #bada55<span class="token punctuation">;</span>

  <span class="token comment">/* Opaques */</span>
  <span class="token property">--color-primary--opacity-10</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    transparent 10%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--opacity-20</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    transparent 20%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>These could be super handy for things like overlays, highlights, or subtle backgrounds.</p>
<h2 id="building-a-colourful-neutral-palette" tabindex="-1">Building A Colourful Neutral Palette</h2>
<p>Your neutral colours, going from white to black could look a little better if they had some of your primary colour in the mix. Using <code>color-mix()</code> makes this super easy:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-black</span><span class="token punctuation">:</span> #000000<span class="token punctuation">;</span>
  <span class="token property">--color-white</span><span class="token punctuation">:</span> #ffffff<span class="token punctuation">;</span>
  <span class="token property">--color-primary</span><span class="token punctuation">:</span> #bada55<span class="token punctuation">;</span>

  <span class="token property">--color-primary--neutral-10</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-black<span class="token punctuation">)</span> 10%<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span> 3%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--neutral-20</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-black<span class="token punctuation">)</span> 20%<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span> 3%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This can give your neutral colour palette a softer tone that feels connected to the primary colour.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>If you define a percentage for both colours, but that percentage does not add up to 100% the remaining percentage of the colour is <code>transparent</code>.</p>
</div>
<h2 id="bringing-it-together" tabindex="-1">Bringing It Together</h2>
<p>So far, we've looked at creating simple tint, shade, opaque, and neutral colour palettes using the <code>color-mix()</code> function. Below is a demo of these colour palettes, include options to:</p>
<ul>
<li>change the primary colour</li>
<li>set the percentage of colour to add to the neutral palette</li>
<li>the CSS of the palettes that can be copied and pasted into your codebase.</li>
</ul>
<div class="at-g-feature">
<iframe height="600" style="width: 100%;" scrolling="no" title="Quick and Dirty Colour Palettes using color-mix()" src="https://codepen.io/sturobson/embed/preview/QwLNpgv?default-tab=result&theme-id=dark" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href="https://codepen.io/sturobson/pen/QwLNpgv">
  Quick and Dirty Colour Palettes using color-mix()</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
</div>
<h2 id="creating-a-'dirty-hack'-dynamic-color-mix()" tabindex="-1">Creating a 'Dirty Hack' Dynamic color-mix()</h2>
<p>For even quicker prototyping you can create a 'dynamic' custom property that uses the <code>*</code> selector.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-primary</span><span class="token punctuation">:</span> #BADA55<span class="token punctuation">;</span>
  <span class="token property">--color-white</span><span class="token punctuation">:</span> #FFFFFF<span class="token punctuation">;</span>
  <span class="token property">--mix-value</span><span class="token punctuation">:</span> 50%<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">*</span> <span class="token punctuation">{</span>
  <span class="token property">--color</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
 in srgb<span class="token punctuation">,</span>
 <span class="token function">var</span><span class="token punctuation">(</span>--custom-color<span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
 <span class="token function">var</span><span class="token punctuation">(</span>--custom-mix-color<span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token function">var</span><span class="token punctuation">(</span>--mix-value<span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="what%E2%80%99s-happening-here%3F" tabindex="-1">What’s Happening Here?</h3>
<ol>
<li><code>--custom-color</code>: Allows you to set a custom colour, which falls back to the <code>--primary-color</code>;</li>
<li><code>--mix-color</code>: Sets a new colour to mix which defaults to <code>--color-white</code>;</li>
<li><code>--mix-value</code>: Controls the percentage of the mix dynamically.</li>
<li><code>*</code>: Declares the calculated <code>--color</code> and makes it available to all elements</li>
</ol>
<h3 id="performance-issues-with-the-*-selector" tabindex="-1">Performance Issues with the * Selector</h3>
<p>While the <code>*</code> selector is useful for experimentation, it’s <strong>not suitable for production</strong> due to potential performance concerns:</p>
<ul>
<li><strong>Recalculation Costs</strong>: Every element on the page could recalculate the --color property whenever --value changes.</li>
<li><strong>Specificity Conflicts</strong>: The <code>*</code> selector applies styles indiscriminately, potentially overriding intended styles.</li>
</ul>
<h2 id="the-future-with-css-functions" tabindex="-1">The Future with CSS Functions</h2>
<p>Looking ahead, <a href="https://css.oddbird.net/sasslike/mixins-functions/">Functions and Mixins in CSS</a> aim to replace common preprocessing patterns by giving CSS authors the ability to define reusable logic natively.</p>
<p>These functions operate in the <strong>value space</strong> of CSS, meaning they compute and return values like colours, lengths, or strings, which can then be assigned to properties.</p>
<p>Combining the CSS <code>color-mix()</code> feature with the proposed custom function syntax could create a better way for dynamic</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--primary-color</span><span class="token punctuation">:</span> #bada55<span class="token punctuation">;</span>
  <span class="token property">--black</span><span class="token punctuation">:</span> #000<span class="token punctuation">;</span>
  <span class="token property">--white</span><span class="token punctuation">:</span> #fff<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token atrule"><span class="token rule">@function</span> <span class="token function">--tint-shade</span><span class="token punctuation">(</span>--color<span class="token punctuation">,</span> --mix-color<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
  <span class="token property">result</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>in srgb<span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--color<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--mix-color<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.component</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">--tint-shade</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--primary-color<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--black<span class="token punctuation">)</span> 10%<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.component:hover</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">--tint-shade</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--primary-color<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">var</span><span class="token punctuation">(</span>--black<span class="token punctuation">)</span> 30%<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This CSS function takes two colours and a percentage and then returns the computed mixed colour for use anywhere it is called in the CSS.</p>
<h3 id="benefits-and-concerns-with-native-css-functions-and-mixins" tabindex="-1">Benefits and Concerns with Native CSS Functions and Mixins</h3>
<p>Native CSS functions and mixins bring some exciting possibilities. They let you skip preprocessors like Sass or PostCSS, which can simplify your workflow by reducing dependencies and build steps.</p>
<p>That said, they’re not without challenges. Performance might take a hit with complex functions that need constant recalculations, like during animations. Planning reusable functions and mixins also requires thought, especially when juggling things like fallbacks or cascading rules.</p>
<p>The W3C is currently exploring this new specification to enhance CSS’s flexibility. As this specification is still under discussion, its details may evolve, it may be some time before we can experiment and use it in production. It's exciting, none-the-less.</p>
<h2 id="using-sass-to-automate-css-custom-properties" tabindex="-1">Using Sass to Automate CSS Custom Properties</h2>
<p>Whilst we're waiting for the cool new CSS with functions and mixins, and if you're already using Sass in your code base we can make things a little easier by using Sass mixins to generate the custom properties - nobody's got time to write (almost) the same code out 10, 20, 30, 40 times.</p>
<p>Here's a little Sass mixin that will generate the CSS custom properties for tint, shade, opaque, and neutral colour palettes</p>
<p>We will use a <code>@for</code> loop to help us, in this example we're only creating a tint colour palette of CSS custom properties:</p>
<pre class="language-scss"><code class="language-scss">
<span class="token keyword">@mixin</span> <span class="token function">generate-color-variables</span><span class="token punctuation">(</span><span class="token variable">$color-name</span><span class="token punctuation">,</span> <span class="token variable">$base-color</span><span class="token punctuation">,</span> <span class="token property"><span class="token variable">$steps</span></span><span class="token punctuation">:</span> 9<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token selector">:root </span><span class="token punctuation">{</span>
  <span class="token comment">// Generate tints</span>
  <span class="token keyword">@for</span> <span class="token variable">$i</span> <span class="token keyword">from</span> 1 <span class="token keyword">through</span> <span class="token selector"><span class="token variable">$steps</span> </span><span class="token punctuation">{</span>
   --<span class="token variable">#{$color-name}</span>--tint-#<span class="token punctuation">{</span><span class="token variable">$i</span> <span class="token operator">*</span> 10<span class="token punctuation">}</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--<span class="token variable">#{$base-color}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> #<span class="token punctuation">{</span><span class="token variable">$i</span> <span class="token operator">*</span> 10<span class="token punctuation">}</span>%
   <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>To make use of the Sass mixin in our code we would need to <code>@include</code> it also:</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@include</span> <span class="token function">generate-color-variables</span><span class="token punctuation">(</span><span class="token string">'color-primary'</span><span class="token punctuation">,</span> <span class="token string">'color-primary'</span><span class="token punctuation">,</span> 10<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This would generate a set of CSS custom properties:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-primary--tint-10</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> 10%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--tint-20</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> 20%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--tint-30</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> 30%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--tint-40</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> 40%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--tint-50</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> 50%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--tint-60</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> 60%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--tint-70</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> 70%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--tint-80</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> 80%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--tint-90</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> 90%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-primary--tint-100</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
    in srgb<span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> 100%
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="the-sass-mixin-in-full" tabindex="-1">The Sass Mixin in Full</h3>
<p>Here is the complete Sass mixin that would generate the four colour palettes as CSS custom properties using <code>color-mix()</code>:</p>
<pre class="language-scss"><code class="language-scss"><span class="token comment">// Mixin to generate CSS custom properties</span>
<span class="token keyword">@mixin</span> <span class="token function">generate-color-variables</span><span class="token punctuation">(</span><span class="token variable">$color-name</span><span class="token punctuation">,</span> <span class="token variable">$base-color</span><span class="token punctuation">,</span> <span class="token property"><span class="token variable">$steps</span></span><span class="token punctuation">:</span> 9<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token selector">:root </span><span class="token punctuation">{</span>
    <span class="token comment">// Generate tints</span>
    <span class="token keyword">@for</span> <span class="token variable">$i</span> <span class="token keyword">from</span> 1 <span class="token keyword">through</span> <span class="token selector"><span class="token variable">$steps</span> </span><span class="token punctuation">{</span>
      --<span class="token variable">#{$color-name}</span>--tint-#<span class="token punctuation">{</span><span class="token variable">$i</span> <span class="token operator">*</span> 10<span class="token punctuation">}</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
        in srgb<span class="token punctuation">,</span>
        <span class="token function">var</span><span class="token punctuation">(</span>--<span class="token variable">#{$base-color}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token function">var</span><span class="token punctuation">(</span>--color-white<span class="token punctuation">)</span> #<span class="token punctuation">{</span><span class="token variable">$i</span> <span class="token operator">*</span> 10<span class="token punctuation">}</span>%
      <span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">// Generate shades</span>
    <span class="token keyword">@for</span> <span class="token variable">$i</span> <span class="token keyword">from</span> 1 <span class="token keyword">through</span> <span class="token selector"><span class="token variable">$steps</span> </span><span class="token punctuation">{</span>
      --<span class="token variable">#{$color-name}</span>--shade-#<span class="token punctuation">{</span><span class="token variable">$i</span> <span class="token operator">*</span> 10<span class="token punctuation">}</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
        in srgb<span class="token punctuation">,</span>
        <span class="token function">var</span><span class="token punctuation">(</span>--<span class="token variable">#{$base-color}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token function">var</span><span class="token punctuation">(</span>--color-black<span class="token punctuation">)</span> #<span class="token punctuation">{</span><span class="token variable">$i</span> <span class="token operator">*</span> 10<span class="token punctuation">}</span>%
      <span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">// Generate opacities</span>
    <span class="token keyword">@for</span> <span class="token variable">$i</span> <span class="token keyword">from</span> 1 <span class="token keyword">through</span> <span class="token selector"><span class="token variable">$steps</span> </span><span class="token punctuation">{</span>
      --<span class="token variable">#{$color-name}</span>--transparency-#<span class="token punctuation">{</span><span class="token variable">$i</span> <span class="token operator">*</span> 10<span class="token punctuation">}</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
        in srgb<span class="token punctuation">,</span>
        <span class="token function">var</span><span class="token punctuation">(</span>--<span class="token variable">#{$base-color}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        transparent #<span class="token punctuation">{</span><span class="token variable">$i</span> <span class="token operator">*</span> 10<span class="token punctuation">}</span>%
      <span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">// Generate Neutral Colours</span>
    <span class="token keyword">@for</span> <span class="token variable">$i</span> <span class="token keyword">from</span> 1 <span class="token keyword">through</span> <span class="token selector"><span class="token variable">$steps</span> </span><span class="token punctuation">{</span>
      --color--neutral-#<span class="token punctuation">{</span><span class="token variable">$i</span> <span class="token operator">*</span> 10<span class="token punctuation">}</span><span class="token punctuation">:</span> <span class="token function">color-mix</span><span class="token punctuation">(</span>
        in srgb<span class="token punctuation">,</span>
        <span class="token function">var</span><span class="token punctuation">(</span>--color-black<span class="token punctuation">)</span> #<span class="token punctuation">{</span><span class="token variable">$i</span> <span class="token operator">*</span> 10<span class="token punctuation">}</span>%<span class="token punctuation">,</span>
        <span class="token function">var</span><span class="token punctuation">(</span>--color-primary<span class="token punctuation">)</span> <span class="token function">var</span><span class="token punctuation">(</span>--neutral-percentage<span class="token punctuation">,</span> 3%<span class="token punctuation">)</span>
      <span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<hr>
<p>I hope I have showed you how simple it can be to quickly create your own colour palettes with <code>color-mix()</code>. Whether you're prototyping or advancing the colour system within your Design System, I think this is a great CSS feature to add to your CSS toolkit.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 5) - Organising Outputs with Style Dictionary</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-5.html"/>
      <updated>2024-12-06T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-5.html</id>
      <content type="html">
        <![CDATA[
        <p>As a design system grows, organising design token outputs can become increasingly important. Without a clear structure, managing tokens could become unwieldy, especially when generating outputs for different platforms or tailoring outputs for specific use cases.</p>
<p>Thoughtfully structuring your token outputs into folders and files creates a scalable foundation that simplifies maintenance and improves collaboration across teams.</p>
<p>In Part 2 of this series, we explored <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-2">how to output design tokens in different formats for various platforms</a>, such as CSS for front-end developers and XML for Android. That article also introduced the idea of grouping outputs into folders to make them easier to locate and use.</p>
<p>In Part 4, we discussed <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-4">how to manipulate token key-value pairs on output to meet specific needs</a>. This included creating custom outputs where necessary and organising them for clarity and usability.</p>
<p>Now, in this fifth tutorial, we'll build on these concepts by focusing on strategies for organising token outputs in greater detail, including how to create file structures that align with your token file structure.</p>
<p>By effectively structuring your token outputs, you enhance usability for your team and future-proof your design system for growth. Let’s dive in!</p>
<h2 id="why-organise-outputs-into-folders-and-files%3F" tabindex="-1">Why Organise Outputs into Folders and Files?</h2>
<p>Organising design token outputs into structured folders and files isn’t just a matter of preference—it’s a best practice that supports scalability, usability, and maintainability. Whether you’re managing a small or large system, a clear organisation strategy ensures that your design tokens remain manageable as the system evolves.</p>
<h3 id="benefits-of-organising-outputs" tabindex="-1">Benefits of Organising Outputs</h3>
<ol>
<li><strong>Easier Maintenance</strong>
A well-organised structure makes it simpler to locate and update specific tokens.</li>
<li><strong>Separation of Concerns</strong>
By splitting tokens into logical groups—such as colours, typography, spacing, and shadows—you ensure that each file focuses on a specific aspect of the design system.</li>
<li><strong>Clarity for Teams</strong>
The separation of design token outputs into logical groups (e.g., colours, typography, spacing) naturally enhances clarity for teams.</li>
</ol>
<h3 id="challenges-of-a-monolithic-tokens-file" tabindex="-1">Challenges of a Monolithic Tokens File</h3>
<p>Starting with a single tokens file (e.g., styles.tokens) may work for small systems, but it becomes problematic as the system scales:</p>
<ul>
<li>Difficulty in Navigation: Large files are harder to read and search, especially for new contributors.</li>
<li>Unintended Changes: Centralising all tokens increases the risk of accidental updates affecting unrelated parts of the system.</li>
<li>Reduced Flexibility: A single file limits the ability to generate tailored outputs for specific contexts, such as themes or platforms.</li>
</ul>
<p>Organising tokens into smaller files and structuring outputs into folders solves these issues, enabling a scalable and efficient design system.</p>
<h2 id="implementing-organised-token-outputs-with-style-dictionary" tabindex="-1">Implementing Organised Token Outputs with Style Dictionary</h2>
<p>Now that we’ve covered the importance of organising token outputs, let’s look at how to implement these practices using Style Dictionary. With the configuration below, we can:</p>
<ul>
<li>Dynamically generate token outputs for specific platforms and formats.</li>
<li>Align the output file structure with the input token structure.</li>
<li>Use filters and transforms to tailor outputs for your design system’s needs.</li>
</ul>
<h3 id="generating-scss-files-from-tokens" tabindex="-1">Generating SCSS Files from Tokens</h3>
<p>We’ll process <code>.tokens</code> files located in <code>src/tokens/</code> to create corresponding <code>.scss</code> files in <code>build/scss/</code>. Each <code>.tokens</code> file generates its own <code>.scss</code> file, keeping outputs modular and easy to navigate.</p>
<p>You can find the complete code for this example in the <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/05-organising-outputs">GitHub repository</a>, on the scss-output-example branch.</p>
<h4 id="example-.tokens-files" tabindex="-1">Example <code>.tokens</code> files</h4>
<p>Below are some sample <code>.tokens</code> files that demonstrate how we are defining Design Tokens in the W3C <code>.tokens</code> formt</p>
<p><strong>color.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#0052cc"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ff4081"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"background"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ffffff"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#333333"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>spacing.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"xs"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"4px"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"sm"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"8px"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"md"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"16px"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"lg"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"32px"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"xl"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"64px"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="style-dictionary-config-file" tabindex="-1">Style Dictionary Config File</h4>
<p>Here is the JavaScript for the configuration needed:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> fs <span class="token keyword">from</span> <span class="token string">'fs'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token comment">// Read all .tokens files from the 'src/tokens' directory</span>
<span class="token keyword">const</span> tokenFiles <span class="token operator">=</span> fs
  <span class="token punctuation">.</span><span class="token function">readdirSync</span><span class="token punctuation">(</span><span class="token string">'src/tokens'</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">file</span><span class="token punctuation">)</span> <span class="token operator">=></span> file<span class="token punctuation">.</span><span class="token function">endsWith</span><span class="token punctuation">(</span><span class="token string">'.tokens'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Configure Style Dictionary</span>
<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">file</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>file<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">scss</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'scss'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/scss/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> tokenFiles<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">file</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token comment">// Replace '.tokens' with '.scss' for the destination</span>
        <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>file<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token string">'.tokens'</span><span class="token punctuation">,</span> <span class="token string">'.scss'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
        <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'scss/variables'</span><span class="token punctuation">,</span>
        <span class="token comment">// Match tokens by filename</span>
        <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> file <span class="token operator">===</span> token<span class="token punctuation">.</span>filePath<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">pop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">hooks</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">transformGroups</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">scss</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'size/pxToRem'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Build all platforms</span>
myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h5 id="key-features-of-the-configuration" tabindex="-1">Key Features of the Configuration</h5>
<ol>
<li><strong>Dynamic File Handling</strong>
Reads all <code>.tokens</code> files from <code>src/tokens</code>, ensuring flexibility as new tokens are added.</li>
<li><strong>Tailored Output Structure</strong>
Each <code>.tokens</code> file generates a corresponding <code>.scss</code> file.</li>
<li><strong>Custom Filters and Transforms</strong>
Filters match tokens to their output files, and transforms (e.g., <code>pxToRem</code>) adapt token values for specific use cases.</li>
<li><strong>Scalable and Maintainable</strong>
Aligning the output file structure with the input token structure simplifies navigation and future updates.</li>
</ol>
<h4 id="example-outputs" tabindex="-1">Example Outputs</h4>
<p>The configuration generates SCSS files like these in the <code>build/scss/</code> directory:</p>
<p><strong>color.scss</strong></p>
<pre class="language-scss"><code class="language-scss"><span class="token comment">// Do not edit directly, this file was auto-generated.</span>

<span class="token property"><span class="token variable">$color-primary</span></span><span class="token punctuation">:</span> #0052cc<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$color-secondary</span></span><span class="token punctuation">:</span> #ff4081<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$color-background</span></span><span class="token punctuation">:</span> #ffffff<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$color-text</span></span><span class="token punctuation">:</span> #333333<span class="token punctuation">;</span></code></pre>
<p><strong>spacing.scss</strong></p>
<pre class="language-scss"><code class="language-scss"><span class="token comment">// Do not edit directly, this file was auto-generated.</span>

<span class="token property"><span class="token variable">$spacing-xs</span></span><span class="token punctuation">:</span> 0.25rem<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-sm</span></span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-md</span></span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-lg</span></span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-xl</span></span><span class="token punctuation">:</span> 4rem<span class="token punctuation">;</span></code></pre>
<p>Organising design token outputs into folders and files is more than a best practice—it’s a cornerstone of an efficient, scalable design system. By following the workflow outlined here and leveraging tools like Style Dictionary, you can:</p>
<ul>
<li>Simplify token management across teams.</li>
<li>Ensure outputs are tailored to platform-specific needs.</li>
<li>Future-proof your design system for growth and collaboration.</li>
</ul>
<p>This approach enhances clarity and usability for your team, laying the foundation for a design system that evolves seamlessly with your organisation’s needs.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 4) - Converting Tokens with Style Dictionary</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-4.html"/>
      <updated>2024-12-05T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-4.html</id>
      <content type="html">
        <![CDATA[
        <p>Implementing Design Tokens can become the backbone of a consistent, scaleable Design System across your organisation and the platforms your products are on. However, different platforms have their own requirements for how names (keys) the values of Design Tokens are expressed and consumed. Whether it is <code>dp</code> for Android, points for iOS, <code>rem</code> for the web, ensuring your Design Tokens work seamlessly across platforms isn't a nice to have, it's essential. And it's possible using Style Dictionary.</p>
<p>Value conversion is the key to making this happen, it allows a single source of truth in your Design Tokens to adapt to the unique needs of each platform you work with. Whilst you might be defining your spacing tokens using pixels (<code>16px</code>), they may need to become rems (<code>1rem</code>) for your CSS, <code>16dp</code> for Android, and <code>16pt</code> for iOS. At the same time, tokens names like <code>spacing.small</code> may need to adapt to naming conventions using kebab-case (<code>--spacing-small</code>) for CSS, your team might want snake_case (<code>spacing_small</code>) for Android, and maybe the JavaScript developers are using camelCase (<code>spacingSmall</code>) throughout the rest of their project.</p>
<p>Without the ability to convert keys and values, a unified Design System could start to break down as it encounters nuances for each platform.</p>
<p>In this fourth tutorial in my Design Tokens workflow series, we will explore how we can use Style Dictionary to handle both key and value conversion, ensuring your tokens are ready for the web, Android, iOS and beyond.</p>
<p>We'll look at practical examples of converting common token types like typography, spacing and colours and dive into how transforms and custom transform groups can adapt tokens for specific needs.</p>
<h2 id="adapting-token-names-for-different-platforms" tabindex="-1">Adapting Token Names for Different Platforms</h2>
<p>Before we take a look at how Style Dictionary can helps use convert the values of our Design Tokens for specific platforms, let's take a look at the possibilities of converting the name (key) of the Design Token.</p>
<p>Out-of-the-box Style Dictionary includes a range of name transform that can convert token keys into different formats. During the build process, these transforms map your source Design Tokens (<code>spacing.small</code>) into platform appropriate naming conventions.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>Before we dive into how Style Dictionary can transform token keys and values to match the desired naming conventions and platform-specific requirements, let’s cover a quick housekeeping item. Moving forward, we’ll use the W3C Community Group’s specification for the .tokens file format to maintain consistency. We are also using version 4.x of Style Dictionary.</p>
</div>
<p>Here's an example of a Design Token</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"small"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"value"</span><span class="token operator">:</span> <span class="token string">"8px"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Small spacing for compact padding or margins."</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="built-in-name-transforms" tabindex="-1">Built-in Name Transforms</h3>
<p>Style Dictionary offers the following commonly used name transforms (there's a noticable change from <code>v3</code> to <code>v4</code> where the <code>/cti</code> has been removed – <code>name/cti/kebab</code> is now <code>name/kebab</code>):</p>
<ol>
<li><strong><code>name/kebab</code></strong> - Converts names to kebab-case, ideal for CSS variables. Example: <code>spacing.small</code> → <code>--spacing-small</code></li>
<li><strong><code>name/camel</code></strong> - Converts names to camelCase, often used in JavaScript or JSON. Example: <code>spacing.small</code> → <code>spacingSmall</code></li>
<li><strong><code>name/snake</code></strong> - Converts names to snake_case, commonly used for Android resource files. Example: <code>spacing.small</code> → <code>spacing_small</code></li>
<li><strong><code>name/pascal</code></strong> - Converts names to PascalCase, often used for constants in Swift or Objective-C. Example: <code>spacing.small</code> → <code>SpacingSmall</code></li>
</ol>
<h4 id="transforming-keys-for-css" tabindex="-1">Transforming Keys for CSS</h4>
<p>We need to register the converting of names and values as part of the specific transform group (platform (web, ios, Android, etc)).</p>
<p>Let’s say you’re generating CSS variables for your tokens and need the keys to follow kebab-case.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.tokens</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'all.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">hooks</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">transformGroups</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'attribute/cti'</span><span class="token punctuation">,</span> <span class="token string">'name/kebab'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Build all platforms</span>
myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--spacing-small</span><span class="token punctuation">:</span> 8px<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>If a team uses camelCase in their JavaScript projects, you can switch to the <code>name/camel</code> transform:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.tokens</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'all.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">hooks</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">transformGroups</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'attribute/cti'</span><span class="token punctuation">,</span> <span class="token string">'name/camelCase'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Build all platforms</span>
myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">export</span> <span class="token keyword">const</span> tokens <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">spacingSmall</span><span class="token operator">:</span> <span class="token string">'8px'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h3 id="when-and-why-to-transform-keys" tabindex="-1">When and Why to Transform Keys</h3>
<p>Key conversion ensures your Design Tokens integrate seamlessly with platform-specific tools and conventions. By automating this step with Style Dictionary, you can:</p>
<ol>
<li>Eliminate manual renaming or inconsistent variable names.</li>
<li>Create outputs that align with developer expectations and team standards.</li>
<li>Simplify collaboration by generating tokens that “speak the language” of their target platform.</li>
</ol>
<h2 id="what-is-value-conversion%3F" tabindex="-1">What is value conversion?</h2>
<p>Design Tokens, at their core, is a shared language for design and development, but that shared language has to speak the specific dialect of each platform that will consume them.</p>
<p>Being able to convert the values of your Design Tokens ensures that the Design Tokens can remain universal, adapting their outputs to meet the need of those platforms and the environments they are implemented in.</p>
<h2 id="style-dictionary-transforms" tabindex="-1">Style Dictionary Transforms</h2>
<p>Transforms in Style Dictionary work by applying rules to tokens during the build process, a transform might convert font sizes from <code>px</code> to <code>rem</code> for CSS or colour from hex (<code>#ff0000</code>) to UIColor formats for iOS. These built-in transforms can ensure that your tokens are translated into the correct units, formats, and structures. Much like add a custom parer as discussed in <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-3">the third post in this series</a>, Style Dictionary allows you to create custom transforms too.</p>
<p>Style Dictionary provides a set of built-in transforms that can take care of this value conversion for the most common use cases:</p>
<ol>
<li>
<p>Dimension Transforms
These are used for spacing, sizing, and other dimensional tokens:</p>
<ul>
<li>size/pxToRem: Converts pixel values (<code>px</code>) to rem values using a base font size (default: <code>16px</code>), example: <code>16px</code> → <code>1rem</code></li>
<li>size/remToDp: Converts pixel values to density-independent pixels (<code>dp</code>) for Android, example: <code>1rem</code> → <code>16dp</code></li>
<li>size/remToPx: Converts <code>rem</code> values back to pixels (<code>px</code>) using a base font size, example: <code>1rem</code> → <code>16px</code></li>
</ul>
</li>
<li>
<p>Colour Transforms
These handle different colour formats for various platforms:</p>
</li>
</ol>
<ul>
<li>color/css: Outputs colours as rgba or hex strings depending on transparency, example: <code>#ff5733</code> → <code>rgba(255, 87, 51, 1)</code></li>
<li>color/hex8android: Outputs an 8-digit hex string for Android, with the alpha channel first, example: <code>#ff5733</code> → <code>#80ff5733</code></li>
<li>color/UIColorSwift: Converts colours into UIColor Swift class format for iOS, example: <code>#ff5733</code> → <code>UIColor(red: 1.0, green: 0.34, blue: 0.2, alpha: 1.0)</code></li>
</ul>
<ol start="3">
<li>Typography Transforms
These handle font-related tokens:</li>
</ol>
<ul>
<li>fontFamily/css: Converts font family tokens into a valid CSS string, adding quotes where necessary, example: <code>[&quot;Arial&quot;, &quot;Helvetica&quot;, &quot;sans-serif&quot;]</code> → <code>'Arial', Helvetica, sans-serif</code></li>
<li>typography/css/shorthand: Outputs a full typography shorthand for CSS, example: <code>{ fontSize: &quot;16px&quot;, fontWeight: &quot;bold&quot; }</code> → <code>bold 16px</code></li>
</ul>
<ol start="4">
<li>Timing and Animation Transforms
Used for timing, easing, and animation properties:</li>
</ol>
<ul>
<li>time/seconds: Converts milliseconds into seconds, example: <code>2000ms</code> → <code>2s</code></li>
<li>cubicBezier/css: Formats cubic bezier values for CSS, example: <code>{ x1: 0.4, y1: 0, x2: 0.2, y2: 1 }</code> → <code>cubic-bezier(0.4, 0, 0.2, 1)</code></li>
</ul>
<ol start="5">
<li>Miscellaneous Transforms
These handle other token types:</li>
</ol>
<ul>
<li>asset/url: Wraps a URL token value in a url() function for CSS, example: &quot;<a href="https://example.com/image.png">https://example.com/image.png</a>&quot; → <code>url(&quot;https://example.com/image.png&quot;)</code></li>
<li>content/quote: Wraps string content in single quotes for CSS, example: Hello → 'Hello'</li>
</ul>
<h2 id="practical-use-cases-for-value-conversion" tabindex="-1">Practical Use Cases for Value Conversion</h2>
<p>Before we take a look at how we can use Style Dictionary to transform the values of the token to the desired values that can be consumed, a brief bit of housekeeping. Moving forward we are going to use the W3C community groups specification for their <code>.tokens</code> file format. I believe this should be the way forward to keep future posts consistent. So, let's get going and transform some values.</p>
<h3 id="converting-px-to-rem-for-the-web" tabindex="-1">Converting <code>px</code> to <code>rem</code> for the Web</h3>
<p>The configuration file for Style Dictionary adds the registration of a transform group, here we are converting <code>px</code> to <code>rem</code> and making sure the generated CSS uses kebab-case.</p>
<p>An example of a spacing design tokens set:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"xs"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"4px"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Extra small spacing for minimal separations or fine-tuned padding."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"s"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"8"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Small spacing for compact padding or margins."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"m"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"16px"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Medium spacing for comfortable padding or margins."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"l"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"24px"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Large spacing for larger separations in layouts."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"xl"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"32px"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Extra large spacing for wide separations or white space."</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.tokens</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'all.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">hooks</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">transformGroups</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'attribute/cti'</span><span class="token punctuation">,</span> <span class="token string">'name/kebab'</span><span class="token punctuation">,</span> <span class="token string">'size/pxToRem'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Build all platforms</span>
myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--spacing-xs</span><span class="token punctuation">:</span> 0.25rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-s</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-m</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-l</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-xl</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>To convert dimension values for other platforms Style Dictionary likes to have you use <code>rem</code> as the tokens value rather than <code>px</code> so you can make use of their built-in transforms.</p>
</div>
<h3 id="converting-rem-to-dp-for-android" tabindex="-1">Converting <code>rem</code> to <code>dp</code> for Android</h3>
<p>An example of a spacing design tokens set:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"xs"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">".25rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Extra small spacing for minimal separations or fine-tuned padding."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"s"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">".5rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Small spacing for compact padding or margins."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"m"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Medium spacing for comfortable padding or margins."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"l"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1.5rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Large spacing for larger separations in layouts."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"xl"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"2rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Extra large spacing for wide separations or white space."</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Style Dictionary includes the size/remToDp (converting <code>rem</code> to <code>dp</code> a) transform as part of its built-in Android transform group, which handles converting rem values into dp for Android. Although this is automatically included, here we are being explicit about its inclusion to show how you can modify or extend this configuration if needed.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.tokens</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">android</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'android'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/android/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'all.xml'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'android/resources'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">hooks</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">transformGroups</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">android</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'attribute/cti'</span><span class="token punctuation">,</span> <span class="token string">'name/snake'</span><span class="token punctuation">,</span> <span class="token string">'size/remToDp'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Build all platforms</span>
myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This gives us the relevant <code>xml</code> for Android.</p>
<pre class="language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dimen</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_xs<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>4.00dp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dimen</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dimen</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_s<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>8.00dp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dimen</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dimen</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_m<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>16.00dp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dimen</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dimen</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_l<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>24.00dp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dimen</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dimen</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_xl<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>32.00dp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dimen</span><span class="token punctuation">></span></span></code></pre>
<h3 id="converting-color-for-swift" tabindex="-1">Converting <code>color</code> for Swift</h3>
<p>Design Tokens often include colours that need to be adapted for different platforms. For example, in Swift development, colours are commonly represented using the UIColor class in Swift. Style Dictionary makes it easy to convert a colour token into this format using the color/UIColorSwift transform.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ff5733"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Primary brand colour used for buttons and links."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#33c1ff"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Secondary brand colour used for accents and highlights."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"tertiary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#75ff33"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Tertiary brand colour used for backgrounds or subtle elements."</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Style Dictionary includes the color/UIColorSwift transform in its built-in ios-swift group. While this transform group automatically converts hex colours into UIColor syntax, we’re explicitly defining the group to demonstrate how you could customise it if needed.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.tokens</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">ios</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'ios'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/ios/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'all.swift'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'ios-swift/class.swift'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">hooks</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">transformGroups</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">ios</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'attribute/cti'</span><span class="token punctuation">,</span> <span class="token string">'name/pascal'</span><span class="token punctuation">,</span> <span class="token string">'color/UIColorSwift'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This gives us a relevant <code>.swift</code> file:</p>
<pre class="language-swift"><code class="language-swift"><span class="token keyword">import</span> <span class="token class-name">UIKit</span>

<span class="token keyword">struct</span> <span class="token class-name">Colors</span> <span class="token punctuation">{</span>
    <span class="token keyword">static</span> <span class="token keyword">let</span> <span class="token class-name">Primary</span> <span class="token operator">=</span> <span class="token class-name">UIColor</span><span class="token punctuation">(</span>red<span class="token punctuation">:</span> <span class="token number">1.0</span><span class="token punctuation">,</span> green<span class="token punctuation">:</span> <span class="token number">0.34</span><span class="token punctuation">,</span> blue<span class="token punctuation">:</span> <span class="token number">0.2</span><span class="token punctuation">,</span> alpha<span class="token punctuation">:</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
    <span class="token keyword">static</span> <span class="token keyword">let</span> <span class="token class-name">Secondary</span> <span class="token operator">=</span> <span class="token class-name">UIColor</span><span class="token punctuation">(</span>red<span class="token punctuation">:</span> <span class="token number">0.2</span><span class="token punctuation">,</span> green<span class="token punctuation">:</span> <span class="token number">0.76</span><span class="token punctuation">,</span> blue<span class="token punctuation">:</span> <span class="token number">1.0</span><span class="token punctuation">,</span> alpha<span class="token punctuation">:</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
    <span class="token keyword">static</span> <span class="token keyword">let</span> <span class="token class-name">Tertiary</span> <span class="token operator">=</span> <span class="token class-name">UIColor</span><span class="token punctuation">(</span>red<span class="token punctuation">:</span> <span class="token number">0.46</span><span class="token punctuation">,</span> green<span class="token punctuation">:</span> <span class="token number">1.0</span><span class="token punctuation">,</span> blue<span class="token punctuation">:</span> <span class="token number">0.2</span><span class="token punctuation">,</span> alpha<span class="token punctuation">:</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="why-be-explicit%3F" tabindex="-1">Why Be Explicit?</h3>
<p>While Style Dictionary provides sensible defaults with its transform groups, being explicit offers several advantages:</p>
<p>• <strong>Clarity:</strong> Teams working on your Design System will immediately understand the transforms being applied without needing to look up defaults.</p>
<p>• <strong>Flexibility:</strong> Explicitly defining the transforms makes it easier to customise them later, for example, if you add a custom transform.</p>
<p>• <strong>Documentation:</strong> For educational purposes or shared configurations, showing the transforms provides a clear example of what’s happening under the hood.</p>
<h2 id="custom-transforms" tabindex="-1">Custom Transforms</h2>
<p>Like the ability to create custom parsers for new file formats in Style Dictionary that <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-3">we discussed in part 3</a> we also have the ability to create custom transforms for names (keys) and values of the Design Tokens.</p>
<p>Let's say we want to use the new <code>color()</code> possibilites of CSS and use <code>color(display-p3)</code> for the websites our Design System supports? We can do this with a custom transform.</p>
<p>First we would need to install a package that would help calculate the values to convert our hex colour code into <code>display-p3</code>. We can use <code>chroma-js</code> for this</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> chroma-js</code></pre>
<p>Then we need to create a new transform in our Style Dictionary config file:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// Ensure chroma-js is installed in your project</span>
<span class="token keyword">const</span> chroma <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'chroma-js'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span><span class="token function">registerTransform</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token comment">// Unique name for the transform</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'color/hexToDisplayP3'</span><span class="token punctuation">,</span>

  <span class="token comment">// This transform modifies the token's value</span>
  <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'value'</span><span class="token punctuation">,</span>

  <span class="token comment">// Applies only to tokens of type "color"</span>
  <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>$type <span class="token operator">===</span> <span class="token string">'color'</span><span class="token punctuation">,</span>

  <span class="token comment">// Convert hex to RGB and format as display-p3</span>
  <span class="token function-variable function">transformer</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> rgb <span class="token operator">=</span> <span class="token function">chroma</span><span class="token punctuation">(</span>token<span class="token punctuation">.</span>$value<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">rgb</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">color(display-p3 </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>rgb<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">/</span> <span class="token number">255</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>rgb<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">/</span> <span class="token number">255</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>rgb<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">/</span> <span class="token number">255</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now, we need to register a new transform group under the hooks.transformGroups property. This allows you to include your custom transform alongside other built-in transforms for a specific platform:</p>
<pre class="language-javascript"><code class="language-javascript">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'./tokens/*.tokens.json'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'web-p3'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/web/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>
        <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'tokens.css'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span>
      <span class="token punctuation">}</span><span class="token punctuation">]</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">hooks</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">transformGroups</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'attribute/cti'</span><span class="token punctuation">,</span> <span class="token string">'name/kebab'</span><span class="token punctuation">,</span> <span class="token string">'color/hexToDisplayP3'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>This would give us a CSS file containing:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-primary</span><span class="token punctuation">:</span> <span class="token function">color</span><span class="token punctuation">(</span>display-p3 1 0.341176 0.2<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-secondary</span><span class="token punctuation">:</span> <span class="token function">color</span><span class="token punctuation">(</span>display-p3 0.2 0.756862 1<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-tertiary</span><span class="token punctuation">:</span> <span class="token function">color</span><span class="token punctuation">(</span>display-p3 0.458824 1 0.2<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="wrapping-up" tabindex="-1">Wrapping Up</h2>
<p>Let's wrap the code we have looked at into a single configuration file, again <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/04-converting-tokens">the code for this post in the series is available on Github</a>.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> chroma <span class="token keyword">from</span> <span class="token string">'chroma-js'</span><span class="token punctuation">;</span>

<span class="token comment">// Register additional transforms</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerTransform</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'color/hexToDisplayP3'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'value'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> token<span class="token punctuation">.</span>$type <span class="token operator">===</span> <span class="token string">'color'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">transform</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> rgb <span class="token operator">=</span> <span class="token function">chroma</span><span class="token punctuation">(</span>token<span class="token punctuation">.</span>$value<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">rgb</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Possible issue here</span>
    <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">color(display-p3 </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>rgb<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">/</span> <span class="token number">255</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>rgb<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">/</span> <span class="token number">255</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>rgb<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">/</span> <span class="token number">255</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Configure Style Dictionary</span>
<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.tokens</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'all.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">android</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'android'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/android/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'all.xml'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'android/resources'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">ios</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'ios-swift'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/ios/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'all.swift'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'ios-swift/class.swift'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">hooks</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">transformGroups</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'attribute/cti'</span><span class="token punctuation">,</span> <span class="token string">'name/kebab'</span><span class="token punctuation">,</span> <span class="token string">'color/hexToDisplayP3'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token literal-property property">android</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token string">'attribute/cti'</span><span class="token punctuation">,</span>
        <span class="token string">'name/snake'</span><span class="token punctuation">,</span>
        <span class="token string">'size/remToSp'</span><span class="token punctuation">,</span>
        <span class="token string">'color/hex8android'</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token literal-property property">ios</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token string">'attribute/cti'</span><span class="token punctuation">,</span>
        <span class="token string">'name/pascal'</span><span class="token punctuation">,</span>
        <span class="token string">'size/swift/remToCGFloat'</span><span class="token punctuation">,</span>
        <span class="token string">'color/UIColorSwift'</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Build all platforms</span>
myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Build completed!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Here we have:</p>
<ul>
<li>added the custom transform to convert hex colours into the <code>color(display-p3)</code> syntax.</li>
<li>used <code>src/tokens/**/*.tokens</code> to look through any folders within <code>src/tokens/</code> and find any files ending in <code>.tokens</code>.</li>
<li>provided the platforms for css, android, and swift (iOS), defined their transform group, where the built files should live, their filename, and what file format they should be in</li>
<li>Been explicit in defining the transforms used for each platforms transform group.</li>
</ul>
<p>Taking these two <code>.tokens</code> file examples:</p>
<p><strong>/tokens/color.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#ff5733"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Primary brand colour used for buttons and links."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#33c1ff"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Secondary brand colour used for accents and highlights."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"tertiary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#75ff33"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Tertiary brand colour used for backgrounds or subtle elements."</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>/tokens/spacing.tokens</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"xs"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">".25rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Extra small spacing for minimal separations or fine-tuned padding."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"s"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">".5rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Small spacing for compact padding or margins."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"m"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Medium spacing for comfortable padding or margins."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"l"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1.5rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Large spacing for larger separations in layouts."</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"xl"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"2rem"</span><span class="token punctuation">,</span>
      <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span><span class="token punctuation">,</span>
      <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"Extra large spacing for wide separations or white space."</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>We get these outputs:</p>
<p><strong>/build/android/all.xml</strong></p>
<pre class="language-xml"><code class="language-xml"><span class="token prolog">&lt;?xml version="1.0" encoding="UTF-8"?></span>

<span class="token comment">&lt;!--
Do not edit directly, this file was auto-generated.
--></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>resources</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>color</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>color_primary<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>#ffff5733<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>color</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>color</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>color_secondary<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>#ff33c1ff<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>color</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>color</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>color_tertiary<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>#ff75ff33<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>color</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dimen</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_xs<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>4.00dp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dimen</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dimen</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_s<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>8.00dp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dimen</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dimen</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_m<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>16.00dp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dimen</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dimen</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_l<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>24.00dp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dimen</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dimen</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_xl<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>32.00dp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dimen</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>resources</span><span class="token punctuation">></span></span></code></pre>
<p><strong>/build/ios/all.swift</strong></p>
<pre class="language-swift"><code class="language-swift"><span class="token comment">//</span>
<span class="token comment">// all.swift</span>
<span class="token comment">//</span>

<span class="token comment">// Do not edit directly, this file was auto-generated.</span>

<span class="token keyword">import</span> <span class="token class-name">UIKit</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> colorPrimary <span class="token operator">=</span> <span class="token class-name">UIColor</span><span class="token punctuation">(</span>red<span class="token punctuation">:</span> <span class="token number">1.000</span><span class="token punctuation">,</span> green<span class="token punctuation">:</span> <span class="token number">0.341</span><span class="token punctuation">,</span> blue<span class="token punctuation">:</span> <span class="token number">0.200</span><span class="token punctuation">,</span> alpha<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> colorSecondary <span class="token operator">=</span> <span class="token class-name">UIColor</span><span class="token punctuation">(</span>red<span class="token punctuation">:</span> <span class="token number">0.200</span><span class="token punctuation">,</span> green<span class="token punctuation">:</span> <span class="token number">0.757</span><span class="token punctuation">,</span> blue<span class="token punctuation">:</span> <span class="token number">1.000</span><span class="token punctuation">,</span> alpha<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> colorTertiary <span class="token operator">=</span> <span class="token class-name">UIColor</span><span class="token punctuation">(</span>red<span class="token punctuation">:</span> <span class="token number">0.459</span><span class="token punctuation">,</span> green<span class="token punctuation">:</span> <span class="token number">1.000</span><span class="token punctuation">,</span> blue<span class="token punctuation">:</span> <span class="token number">0.200</span><span class="token punctuation">,</span> alpha<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> spacingL <span class="token operator">=</span> <span class="token class-name">CGFloat</span><span class="token punctuation">(</span><span class="token number">24.00</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> spacingM <span class="token operator">=</span> <span class="token class-name">CGFloat</span><span class="token punctuation">(</span><span class="token number">16.00</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> spacingS <span class="token operator">=</span> <span class="token class-name">CGFloat</span><span class="token punctuation">(</span><span class="token number">8.00</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> spacingXl <span class="token operator">=</span> <span class="token class-name">CGFloat</span><span class="token punctuation">(</span><span class="token number">32.00</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> spacingXs <span class="token operator">=</span> <span class="token class-name">CGFloat</span><span class="token punctuation">(</span><span class="token number">4.00</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>/build/css/all.css</strong></p>
<pre class="language-css"><code class="language-css"><span class="token comment">/**
 * Do not edit directly, this file was auto-generated.
 */</span>

<span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-primary</span><span class="token punctuation">:</span> <span class="token function">color</span><span class="token punctuation">(</span>display-p3 1 0.3411764705882353 0.2<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-secondary</span><span class="token punctuation">:</span> <span class="token function">color</span><span class="token punctuation">(</span>display-p3 0.2 0.7568627450980392 1<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--color-tertiary</span><span class="token punctuation">:</span> <span class="token function">color</span><span class="token punctuation">(</span>display-p3 0.4588235294117647 1 0.2<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">--spacing-xs</span><span class="token punctuation">:</span> 0.25rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-s</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-m</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-l</span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-xl</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Adapting Design Token names (keys) and values is essential for creating a scalable and maintainable Design System. These practices ensure that your tokens align with the specific needs of each team and platform while maintaining consistency across your Design System. By providing platform-specific outputs, developers can seamlessly integrate tokens into their workflows, fostering better collaboration across teams.</p>
<p>Hopefully, this article has clarified how to adapt Design Tokens effectively for different platforms. By utilising transforms and transform groups in Style Dictionary, you can ensure your Design System remains consistent and scalable while meeting the unique requirements of every platform your team supports.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>The Faculty Of Design Systems</title>
      <link href="https://www.alwaystwisted.com/articles/the-faculty-of-design-systems.html"/>
      <updated>2024-12-02T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/the-faculty-of-design-systems.html</id>
      <content type="html">
        <![CDATA[
        <p>I reached my late teenage years at almost the perfect time for a horror fan. The late 1990s saw a resurgence of the genre in the film industry. Sparked by the success of <em>Scream</em> in 1996, Dimension Films went through every drawer of its writer, Kevin Williamson, to see what other delights he’d written.</p>
<p>In 1997, <em>I Know What You Did Last Summer</em> was released, and in 1998, Williamson’s cross-genre <em>The Faculty</em> brought science fiction and horror to a small town in Ohio.</p>
<p>Much like Dawson and Joey discussing the best Spielberg films in <em>Dawson’s Creek</em> (another Williamson creation), these movies were packed with references to older films in their respective genres. They didn’t just tell their own stories, they built on the cultural DNA of what came before, remixing familiar tropes in clever and unexpected ways.</p>
<p>It’s fitting, then, that one of my favourite lines from <em>The Faculty</em> has stuck with me:</p>
<blockquote>
If you were going to take over the world, would you blow up the White House *Independence Day* style, or sneak in through the back door?
<cite>Casey Connor (The Faculty, 1998)</cite>
</blockquote>
<p>This question isn’t just about alien invasions, it’s a perfect metaphor for introducing something new, like a Design System, into a complex organisation.</p>
<p>Do you go in with fireworks and a grand unveiling, or do you quietly work your way into the structure until it becomes part of the system’s DNA?</p>
<h2 id="invasion-of-the-design-system" tabindex="-1">Invasion of the Design System</h2>
<p>Like a subtle sci-fi horror movie, building a Design System doesn’t have to involve loud bangs and big drama. Sometimes, it’s about quietly embedding it into existing workflows and teams until it becomes an essential part of how your organisation works.</p>
<p>Your Design System doesn’t need to arrive in a spaceship over the White House to make an impact. Instead, think of it like the creeping unease of <em>Invasion of the Body Snatchers</em>, quietly infiltrating workflows and processes until it’s simply part of the organisation’s DNA.</p>
<p>When a system is gradually built, integrated into workflows, and consistently demonstrates its value, it has the power to become indispensable. It’s like a well-executed plot twist: surprising when revealed, yet inevitable in hindsight.</p>
<p>This method can be particularly effective when resources are scarce, or when approval for a formal Design System isn’t yet on the table. Start small: address a persistent inconsistency, introduce a handful of design tokens, or offer a reusable component that saves a team time. Each small improvement fosters trust, demonstrates value, and lays the groundwork for broader adoption.</p>
<p>Like the best slow-burn horror films, this approach leaves a lasting impression. A Design System developed this way isn’t just a tool—it becomes part of the culture, shaping how teams think, work, and collaborate.</p>
<h2 id="the-big-explosion-vs.-the-quiet-revolution" tabindex="-1">The Big Explosion vs. The Quiet Revolution</h2>
<p>You could launch your Design System with fireworks, a grand unveiling like the <em>Independence Day</em> mothership making its dramatic entrance. But while a big, bold debut gets attention, it can also create chaos.</p>
<p>The reality is that a “big bang” approach can cause as many problems as it solves. It risks alienating the very people you need to win over. This is where the <em>quiet revolution</em> comes in—slowly integrating the system into workflows, proving its value piece by piece, and growing adoption naturally over time.</p>
<h3 id="the-risks-of-the-big-bang-approach" tabindex="-1">The Risks of the Big Bang Approach</h3>
<p>The “big bang” might sound appealing, but it can backfire:</p>
<ul>
<li><strong>“We don’t have time to use this.”</strong> - Teams drowning in deliverables might feel the system is an added burden.</li>
<li><strong>“Why weren’t we consulted?”</strong> - A top-down approach can alienate teams who feel excluded.</li>
<li><strong>“We already have our own components.”</strong> - Teams may view the system as redundant or even a threat.</li>
<li><strong>“Why is this being driven by that team?”</strong> - Questions about ownership can undermine trust.</li>
</ul>
<p>Big explosions might grab attention, but they often fizzle out when enthusiasm fades or resistance builds. The initial buzz doesn’t guarantee lasting adoption.</p>
<h3 id="why-a-quiet-revolution-can-work" tabindex="-1">Why a Quiet Revolution can work</h3>
<p>The quiet revolution is about creating change subtly, like the creeping takeover in <em>Invasion of the Body Snatchers</em>. By solving immediate pain points and offering tangible benefits, you build trust and adoption naturally.</p>
<ul>
<li><strong>Start small</strong> - Introduce a reusable component or a few design tokens that make work easier.</li>
<li><strong>Listen and adapt</strong> - Engage with teams to understand their challenges and incorporate their feedback.</li>
<li><strong>Be visible, but not intrusive</strong> - Show you’re there to help without forcing adoption.</li>
</ul>
<p>Over time, these small wins add up, creating a network of advocates who spread the system organically. By the time the system is fully adopted, it will feel like it was always meant to be there—an integral part of how your organisation works.</p>
<h2 id="small-team%2C-big-impact" tabindex="-1">Small Team, Big Impact</h2>
<p>Many Design Systems don’t begin with fanfare but with a handful of dedicated individuals—designers, developers, or both—quietly working behind the scenes. They’re like the small group of survivors in a horror movie, spotting the patterns others miss and taking action before it’s too late.</p>
<p>A grassroots approach often starts with small, practical observations:</p>
<ul>
<li>Multiple teams solving the same problems in slightly different ways.</li>
<li>Buttons that look similar but behave inconsistently.</li>
<li>Spacing that’s inconsistent between screens.</li>
<li>Colours that fail accessibility standards.</li>
</ul>
<p>These individuals think, <em>&quot;What if we standardise this?&quot;</em> And with that, the seeds of a Design System are planted.</p>
<h3 id="success-through-subtlety" tabindex="-1">Success Through Subtlety</h3>
<p>Small teams have the advantage of working under the radar, avoiding the pressure of delivering a fully-formed system from day one. Instead, they focus on incremental improvements, such as:</p>
<ul>
<li><strong>Streamlining repetitive work</strong> - A shared button or token set that saves time.</li>
<li><strong>Improving quality</strong> - Standardising patterns to reduce bugs and ensure accessibility compliance.</li>
<li><strong>Building trust</strong> - Demonstrating the benefits of consistency through visible, small wins.</li>
</ul>
<p>Over time, these efforts create momentum. The Design System becomes less about imposing change and more about solving shared problems. As teams experience its benefits, they naturally adopt it—and even advocate for it.</p>
<h2 id="incremental-buy-in%3A-one-step-at-a-time" tabindex="-1">Incremental Buy-in: One Step at a Time</h2>
<p>Invasion isn’t about force; it’s about persistence. Securing buy-in for a Design System works the same way—through small, meaningful steps that show value without overwhelming anyone.</p>
<p>Rolling out the system incrementally—one component, one team at a time—reduces resistance. Start with something manageable: a shared button component, a small set of tokens, or a consistent typography scale. These changes demonstrate immediate value, building trust and encouraging further adoption.</p>
<h3 id="creating-a-network-of-champions" tabindex="-1">Creating a Network of Champions</h3>
<p>When teams see tangible benefits, they become advocates. A developer might share how a component saved hours of work, or a designer might explain how tokens improved consistency. These champions spread enthusiasm, making adoption feel natural and organic.</p>
<h3 id="from-steps-to-a-movement" tabindex="-1">From Steps to a Movement</h3>
<p>Incremental improvements grow over time, turning the Design System into something larger—a movement. By the time the system is fully integrated, it won’t feel like an external addition but a natural extension of how the organisation operates.</p>
<h2 id="communicate-first%2C-build-second" tabindex="-1">Communicate First, Build Second</h2>
<p>A quiet revolution thrives on communication. Without clear dialogue, even the best-crafted system risks being misunderstood or ignored. Start with the <em>why?</em> Why does the system exist? What problems does it solve? When teams understand its value, they’re more likely to engage and advocate for it.</p>
<p>Communication isn’t just about delivering a message; it’s about fostering collaboration. By gathering feedback and involving teams in the process, the system becomes a shared effort rather than a top-down directive. Like the subtle infiltration in <em>Invasion of the Body Snatchers</em>, effective communication quietly plants the system’s seeds, helping it take root and grow naturally within the organisation.</p>
<h2 id="design-systems-as-culture%3A-a-movement%2C-not-a-mandate" tabindex="-1">Design Systems as Culture: A Movement, Not a Mandate</h2>
<p>Much like <em>Invasion of the Body Snatchers</em>, a Design System’s success lies in its gradual and understated integration. Over time, it reshapes how people think, work, and collaborate until it becomes an inseparable part of the organisation’s DNA—something so ingrained that no one remembers a time without it.</p>
<p>By the time the system is fully adopted, it won’t feel like a revolution—it’ll feel like the way things have always been done. And like the best slow-burn stories, its impact will be enduring, shaping how the organisation evolves and grows for years to come.</p>
<p>By the time anyone notices, it’s already everywhere.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Capturing URLs to Obsidian with a Bookmarklet</title>
      <link href="https://www.alwaystwisted.com/articles/capturing-urls-to-obsidian-with-a-bookmarklet.html"/>
      <updated>2024-11-29T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/capturing-urls-to-obsidian-with-a-bookmarklet.html</id>
      <content type="html">
        <![CDATA[
        <p>Many of us come across interesting articles, tools, or resources online and wish to save them for later reference. Over the last couple of years I've tried using an application to keep all of my 'notes' in one place and recently moved to Obsidian.</p>
<p>I wanted a bookmarklet that would help me save interesting web pages to my Obsidian Vault so I can access it at a later date. I could use the browsers native bookmarking tools but I'm often across browsers throughout my working day. I could use available third-party tools - but I want to try to keep 'everything' in markdown, in Obsidian. This article you're reading now started off in Obsidian.</p>
<p>In this post, I’ll walk you through the bookmarklet, how it works, and how you can use it to streamline your bookmarking workflow.</p>
<h2 id="what-the-bookmarklet-does" tabindex="-1">What the Bookmarklet Does</h2>
<p>This bookmarklet allows you to:</p>
<ul>
<li>Capture the current webpage title and URL.</li>
<li>Optionally modify the title.</li>
<li>Add tags for easier categorisation.</li>
<li>Extract metadata like descriptions, images, and publication dates when available.</li>
<li>Save all this information directly into your specified folder in your Obsidian vault.</li>
</ul>
<h2 id="the-full-code" tabindex="-1">The full code</h2>
<pre class="language-javascript"><code class="language-javascript"><span class="token literal-property property">javascript</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> vault <span class="token operator">=</span> <span class="token string">'everything'</span><span class="token punctuation">;</span> <span class="token comment">// Your Obsidian vault name</span>
  <span class="token keyword">const</span> folder <span class="token operator">=</span> <span class="token string">'bookmarks'</span><span class="token punctuation">;</span> <span class="token comment">// Folder for all bookmarks</span>
  <span class="token keyword">let</span> title <span class="token operator">=</span> <span class="token function">prompt</span><span class="token punctuation">(</span><span class="token string">'Want to change the title?'</span><span class="token punctuation">,</span> document<span class="token punctuation">.</span>title<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> askForTags <span class="token operator">=</span> <span class="token function">prompt</span><span class="token punctuation">(</span><span class="token string">'Enter any tags, comma separated'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">let</span> tags <span class="token operator">=</span> askForTags <span class="token operator">?</span> askForTags<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">','</span><span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

  <span class="token comment">// Function to format tags: remove spaces, replace with hyphens, add #</span>
  <span class="token keyword">function</span> <span class="token function">formatHashtags</span><span class="token punctuation">(</span><span class="token parameter">arr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> arr<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">str</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token string">'#'</span> <span class="token operator">+</span> str<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\s+</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">' '</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  tags <span class="token operator">=</span> <span class="token function">formatHashtags</span><span class="token punctuation">(</span>tags<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> url <span class="token operator">=</span> document<span class="token punctuation">.</span>location<span class="token punctuation">.</span>href<span class="token punctuation">;</span>

  <span class="token comment">// Try to grab meta description or OG description</span>
  <span class="token keyword">let</span> description <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> metaDescription <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'meta[name="description"]'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> ogDescription <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span>
    <span class="token string">'meta[property="og:description"]'</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">if</span> <span class="token punctuation">(</span>metaDescription<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    description <span class="token operator">=</span> metaDescription<span class="token punctuation">.</span>content<span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>ogDescription<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    description <span class="token operator">=</span> ogDescription<span class="token punctuation">.</span>content<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// Try to grab OG image, Twitter image, or other social image</span>
  <span class="token keyword">let</span> imageUrl <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> ogImage <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'meta[property="og:image"]'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> twitterImage <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'meta[name="twitter:image"]'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">if</span> <span class="token punctuation">(</span>ogImage<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    imageUrl <span class="token operator">=</span> ogImage<span class="token punctuation">.</span>content<span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>twitterImage<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    imageUrl <span class="token operator">=</span> twitterImage<span class="token punctuation">.</span>content<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// Try to grab article:published_time</span>
  <span class="token keyword">let</span> publishedDate <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> publishedTime <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span>
    <span class="token string">'meta[property="article:published_time"]'</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>publishedTime<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> pubDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span>publishedTime<span class="token punctuation">.</span>content<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> pubDay <span class="token operator">=</span> <span class="token function">String</span><span class="token punctuation">(</span>pubDate<span class="token punctuation">.</span><span class="token function">getDate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">padStart</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> pubMonth <span class="token operator">=</span> <span class="token function">String</span><span class="token punctuation">(</span>pubDate<span class="token punctuation">.</span><span class="token function">getMonth</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">padStart</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Months are zero-indexed</span>
    <span class="token keyword">const</span> pubYear <span class="token operator">=</span> pubDate<span class="token punctuation">.</span><span class="token function">getFullYear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    publishedDate <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Published on </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>pubDay<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>pubMonth<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>pubYear<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token comment">// Format as DD-MM-YYYY</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// Sanitise title to remove invalid filename characters</span>
  title <span class="token operator">=</span> title<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">[\\/:*?"&lt;>|]</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// Generate DD-MM-YYYY timestamp format</span>
  <span class="token keyword">const</span> now <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> day <span class="token operator">=</span> <span class="token function">String</span><span class="token punctuation">(</span>now<span class="token punctuation">.</span><span class="token function">getDate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">padStart</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> month <span class="token operator">=</span> <span class="token function">String</span><span class="token punctuation">(</span>now<span class="token punctuation">.</span><span class="token function">getMonth</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">padStart</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'0'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Months are zero-indexed</span>
  <span class="token keyword">const</span> year <span class="token operator">=</span> now<span class="token punctuation">.</span><span class="token function">getFullYear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> formattedDate <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>day<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>month<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>year<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token comment">// DD-MM-YYYY format</span>

  <span class="token keyword">const</span> fileName <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>folder<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>title<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token comment">// Unique file name</span>

  <span class="token comment">// Format content with title, date, image, description, URL, and tags</span>
  <span class="token keyword">const</span> imageMarkdown <span class="token operator">=</span> imageUrl <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">![Image](</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>imageUrl<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)\n\n</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">;</span> <span class="token comment">// Add markdown image if URL exists</span>
  <span class="token keyword">const</span> content <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>publishedDate<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">Saved on </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>formattedDate<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>imageMarkdown<span class="token interpolation-punctuation punctuation">}</span></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> description <span class="token operator">+</span> <span class="token string">'\n\n'</span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">- [Visit the page](</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>url<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)\n\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>tags<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>

  document<span class="token punctuation">.</span>location<span class="token punctuation">.</span>href <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">obsidian://new?file=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token function">encodeURIComponent</span><span class="token punctuation">(</span>fileName<span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&amp;content=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token function">encodeURIComponent</span><span class="token punctuation">(</span>content<span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&amp;vault=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>vault<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="breaking-down-the-code" tabindex="-1">Breaking Down the Code</h2>
<p>The bookmarklet uses JavaScript to gather data from the current webpage and construct a new note in your Obsidian vault. Let’s break it into steps.</p>
<h3 id="setting-up-the-vault-and-folder" tabindex="-1">Setting Up the Vault and Folder</h3>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> vault <span class="token operator">=</span> <span class="token string">'everything'</span><span class="token punctuation">;</span> <span class="token comment">// Your Obsidian vault name</span>
<span class="token keyword">const</span> folder <span class="token operator">=</span> <span class="token string">'bookmarks'</span><span class="token punctuation">;</span> <span class="token comment">// Folder for bookmarks in your vault</span></code></pre>
<p>These constants define where the captured notes will be stored. Replace <code>everything</code> and <code>bookmarks</code> with the name of your vault and the desired folder path.</p>
<h3 id="prompting-for-the-title-and-tags" tabindex="-1">Prompting for the Title and Tags</h3>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">let</span> title <span class="token operator">=</span> <span class="token function">prompt</span><span class="token punctuation">(</span><span class="token string">'Want to change the title?'</span><span class="token punctuation">,</span> document<span class="token punctuation">.</span>title<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> askForTags <span class="token operator">=</span> <span class="token function">prompt</span><span class="token punctuation">(</span><span class="token string">'Enter any tags, comma separated'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> tags <span class="token operator">=</span> askForTags <span class="token operator">?</span> askForTags<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">','</span><span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span></code></pre>
<p><strong>Title:</strong> The script captures the webpage’s title (document.title) and gives you the option to modify it via a prompt.
<strong>Tags:</strong> You can enter tags separated by commas to categorise the bookmark. If you skip this, the tags will remain empty.</p>
<h3 id="formatting-tags" tabindex="-1">Formatting Tags</h3>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">function</span> <span class="token function">formatHashtags</span><span class="token punctuation">(</span><span class="token parameter">arr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> arr<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">str</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token string">'#'</span> <span class="token operator">+</span> str<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\s+</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">' '</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
tags <span class="token operator">=</span> <span class="token function">formatHashtags</span><span class="token punctuation">(</span>tags<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This function:</p>
<ul>
<li>Trims whitespace from each tag.</li>
<li>Replaces spaces with hyphens to make tags URL-friendly.</li>
<li>Prepends a # to each tag, turning them into Obsidian-compatible hashtags.</li>
</ul>
<h3 id="extracting-metadata" tabindex="-1">Extracting Metadata</h3>
<h4 id="description" tabindex="-1">Description</h4>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> metaDescription <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'meta[name="description"]'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> ogDescription <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'meta[property="og:description"]'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> description <span class="token operator">=</span> metaDescription
  <span class="token operator">?</span> metaDescription<span class="token punctuation">.</span>content
  <span class="token operator">:</span> ogDescription
    <span class="token operator">?</span> ogDescription<span class="token punctuation">.</span>content
    <span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">;</span></code></pre>
<p>This retrieves the webpage’s description from <meta> tags.</p>
<h4 id="image" tabindex="-1">Image</h4>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> ogImage <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'meta[property="og:image"]'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> twitterImage <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'meta[name="twitter:image"]'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> imageUrl <span class="token operator">=</span> ogImage
  <span class="token operator">?</span> ogImage<span class="token punctuation">.</span>content
  <span class="token operator">:</span> twitterImage
    <span class="token operator">?</span> twitterImage<span class="token punctuation">.</span>content
    <span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">;</span></code></pre>
<p>The script looks for Open Graph or Twitter image metadata to include a thumbnail.</p>
<h4 id="published-date" tabindex="-1">Published Date</h4>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> publishedTime <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span>
  <span class="token string">'meta[property="article:published_time"]'</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> publishedDate <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>publishedTime<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> pubDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span>publishedTime<span class="token punctuation">.</span>content<span class="token punctuation">)</span><span class="token punctuation">;</span>
  publishedDate <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Published on </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>pubDate<span class="token punctuation">.</span><span class="token function">toLocaleDateString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>It checks for the publication date in the <meta> tags and formats it.</p>
<h3 id="sanitising-the-title" tabindex="-1">Sanitising the Title</h3>
<pre class="language-javascript"><code class="language-javascript">title <span class="token operator">=</span> title<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">[\\/:*?"&lt;>|]</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This step ensures the title is valid for file names by removing characters that might cause issues.</p>
<h3 id="constructing-the-note" tabindex="-1">Constructing the Note</h3>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> imageMarkdown <span class="token operator">=</span> imageUrl <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">![Image](</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>imageUrl<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)\n\n</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> content <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>publishedDate<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">Saved on </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>formattedDate<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>imageMarkdown<span class="token interpolation-punctuation punctuation">}</span></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description <span class="token operator">?</span> description <span class="token operator">+</span> <span class="token string">'\n\n'</span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">- [Visit the page](</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>url<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)\n\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>tags<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span></code></pre>
<p>The script then formats the note with the collected data:</p>
<ul>
<li>Includes metadata (date, description, and image).</li>
<li>Appends the URL.</li>
<li>Adds any tags you’ve entered.</li>
</ul>
<h3 id="sending-the-note-to-obsidian" tabindex="-1">Sending the Note to Obsidian</h3>
<pre class="language-javascript"><code class="language-javascript">document<span class="token punctuation">.</span>location<span class="token punctuation">.</span>href <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">obsidian://new?file=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token function">encodeURIComponent</span><span class="token punctuation">(</span>fileName<span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&amp;content=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token function">encodeURIComponent</span><span class="token punctuation">(</span>content<span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&amp;vault=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>vault<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span></code></pre>
<p>Finally, the script redirects you to Obsidian’s URI scheme to create the note. This sends the note to the specified folder in your vault using Obsidian’s <code>obsidian://</code> protocol.</p>
<h2 id="how-to-use-the-bookmarklet" tabindex="-1">How to Use the Bookmarklet</h2>
<ul>
<li>Customise It:
<ul>
<li>Copy the full JavaScript code.</li>
<li>Edit the vault and folder variables to match your Obsidian setup.</li>
</ul>
</li>
<li>Create the Bookmarklet:
<ul>
<li>Create a new bookmark in Safari and paste the code into the URL field.</li>
</ul>
</li>
<li>Use It:
<ul>
<li>While browsing, click the bookmarklet.</li>
<li>Enter a title and tags (optional).</li>
<li>The note will appear in your Obsidian vault.</li>
</ul>
</li>
</ul>
<p>These steps should work in all modern browsers, I've only used this in Safari.</p>
<h2 id="hot-linking" tabindex="-1">Hot Linking</h2>
<p>When you save a url as a bookmark in Obsidian the image that is save d is the url, we are hot-linking to someone else's resource on their server. That's not nice, so I created a node script that would</p>
<ul>
<li>look into the bookmarks folder</li>
<li>find the image url in a markdown file</li>
<li>download the image to an <code>assets</code> folder in my vault</li>
<li>replace the hot link with the local link</li>
</ul>
<p>Here's the script:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> axios <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'axios'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> path <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> obsidianVaultPath <span class="token operator">=</span> <span class="token string">'/your/path/to/your/obsidian/vault'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> bookmarksFolderPath <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>
  obsidianVaultPath<span class="token punctuation">,</span>
  <span class="token string">'your/bookmark/folder'</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> imageSavePath <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>bookmarksFolderPath<span class="token punctuation">,</span> <span class="token string">'your/images/folder'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>fs<span class="token punctuation">.</span><span class="token function">existsSync</span><span class="token punctuation">(</span>imageSavePath<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  fs<span class="token punctuation">.</span><span class="token function">mkdirSync</span><span class="token punctuation">(</span>imageSavePath<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token literal-property property">recursive</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Download the image and save it locally</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">downloadImage</span><span class="token punctuation">(</span><span class="token parameter">imageUrl<span class="token punctuation">,</span> saveFolder</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token keyword">await</span> axios<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>imageUrl<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token literal-property property">responseType</span><span class="token operator">:</span> <span class="token string">'arraybuffer'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>response<span class="token punctuation">.</span>status <span class="token operator">===</span> <span class="token number">200</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> imageFilename <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>saveFolder<span class="token punctuation">,</span> path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>imageUrl<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      fs<span class="token punctuation">.</span><span class="token function">writeFileSync</span><span class="token punctuation">(</span>imageFilename<span class="token punctuation">,</span> response<span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Image downloaded and saved as: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>imageFilename<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> imageFilename<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">'Error downloading image:'</span><span class="token punctuation">,</span> error<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// Process a note</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">processNote</span><span class="token punctuation">(</span><span class="token parameter">noteFilePath</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> noteContent <span class="token operator">=</span> fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span>noteFilePath<span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> imageRegex <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">!\[\]\((http[s]?:\/\/[^\)]+)\)</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> matches <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">...</span>noteContent<span class="token punctuation">.</span><span class="token function">matchAll</span><span class="token punctuation">(</span>imageRegex<span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

    <span class="token keyword">if</span> <span class="token punctuation">(</span>matches<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">const</span> match <span class="token keyword">of</span> matches<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> imageUrl <span class="token operator">=</span> match<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Found image URL: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>imageUrl<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">const</span> localImagePath <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">downloadImage</span><span class="token punctuation">(</span>imageUrl<span class="token punctuation">,</span> imageSavePath<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>localImagePath<span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token keyword">const</span> localImageFilename <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>localImagePath<span class="token punctuation">)</span><span class="token punctuation">;</span>
          noteContent <span class="token operator">=</span> noteContent<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span>
            imageUrl<span class="token punctuation">,</span>
            <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">../assets/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>localImageFilename<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span>
          <span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
      fs<span class="token punctuation">.</span><span class="token function">writeFileSync</span><span class="token punctuation">(</span>noteFilePath<span class="token punctuation">,</span> noteContent<span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Note updated: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>noteFilePath<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">No image URLs found in: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>noteFilePath<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Error processing note: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>noteFilePath<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> error<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// Process all markdown files in the bookmarks folder</span>
<span class="token keyword">function</span> <span class="token function">processAllNotes</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> files <span class="token operator">=</span> fs<span class="token punctuation">.</span><span class="token function">readdirSync</span><span class="token punctuation">(</span>bookmarksFolderPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> mdFiles <span class="token operator">=</span> files<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">file</span><span class="token punctuation">)</span> <span class="token operator">=></span> file<span class="token punctuation">.</span><span class="token function">endsWith</span><span class="token punctuation">(</span><span class="token string">'.md'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    mdFiles<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">file</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> noteFilePath <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>bookmarksFolderPath<span class="token punctuation">,</span> file<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token function">processNote</span><span class="token punctuation">(</span>noteFilePath<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">'Error processing files:'</span><span class="token punctuation">,</span> error<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token function">processAllNotes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>You will need to update the <code>obsidianVaultPath</code> and <code>bookmarksFolderPath</code> and also install axios (<code>npm install axios</code>).</p>
<p>There's a few issues with this script that I want to address -- sometimes the OG image is not a png, it seems Obisdian doesn't support something like WebP. If the image returned isn't recognised you would get the text of the file (better than hot-linking in my opinion).</p>
<p>In the future, I plan to share this on GitHub to make it easier for others to explore and contribute. I might even refine it further, like converting all images to PNG for consistency.</p>
<p>Initially, I considered adding a ‘to be sorted’ folder to organise bookmarks, but I realised tags provide an equally efficient solution.</p>
<p>I hope this inspires you to craft a bookmarking system that fits your workflow, especially if you’re using Obsidian.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 3) - Beyond JSON: Exploring File Formats for Design Tokens</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-3.html"/>
      <updated>2024-11-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-3.html</id>
      <content type="html">
        <![CDATA[
        <p>Before we go further into the tutorial series I thought we should take a look at the file formats you can use to generate your Design Tokens into the file outputs you need.</p>
<p>The code for this part of the series <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/03-beyond-json">available to look at on Github</a>.</p>
<p>While <code>.json</code> is the most common and natively supported format in Style Dictionary, it’s not the only option. When working with design tokens, choosing the right file format is crucial for readability, maintainability, and collaboration.</p>
<p>While <code>.json</code> is a great starting point for defining design tokens, it’s not always the most human-readable or flexible option, especially for larger or more complex token files. Custom parsers bridge this gap by enabling Style Dictionary to interpret other formats like <code>.yaml</code>, <code>.hjson</code>, <code>.json5</code>, and the <a href="https://www.designtokens.org">Design Tokens Working Group</a> formats <code>.tokens</code> and <code>.tokens.json</code>, giving you the freedom to choose what format best suits your team’s needs.</p>
<h2 id="let's-look-at-file-formats" tabindex="-1">Let's Look At File Formats</h2>
<h3 id=".json" tabindex="-1"><code>.json</code></h3>
<p>JSON is natively supported by Style Dictionary, making it the easiest format to start with. Its rigid structure ensures compatibility across platforms and tools, but the verbose syntax of braces, quotes, and commas could be challenging for large or deeply nested token sets.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#007bff"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id=".yaml" tabindex="-1"><code>.yaml</code></h3>
<p>YAML is a human-readable, indentation-based syntax that reduces visual clutter, making it easier to manage for humans. It can especially useful for large, nested token sets and teams with non-developers, such as designers, working with token files.</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token key atrule">color</span><span class="token punctuation">:</span>
  <span class="token key atrule">primary</span><span class="token punctuation">:</span>
    $value<span class="token punctuation">:</span> <span class="token string">'#007bff'</span></code></pre>
<h3 id=".json5" tabindex="-1"><code>.json5</code></h3>
<p>JSON5 (JSON for humans) enhances JSON by allowing comments, trailing commas, and unquoted keys, making it a more forgiving and developer-friendly format. It’s a great option if you want JSON compatibility but also need to include notes or reduce syntax errors.</p>
<pre class="language-json5"><code class="language-json5"><span class="token punctuation">{</span>
  <span class="token comment">// Primary color</span>
  <span class="token property unquoted">color</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property unquoted">primary</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property unquoted">$value</span><span class="token operator">:</span> <span class="token string">'#007bff'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span></code></pre>
<h3 id=".hjson" tabindex="-1"><code>.hjson</code></h3>
<p>HJSON simplifies JSON by removing the need for strict punctuation, making it more human-readable. It could be a good middle ground between YAML’s simplicity and JSON’s structure.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#007bff"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id=".tokens-and-.tokens.json" tabindex="-1"><code>.tokens</code> and <code>.tokens.json</code></h3>
<p>The <code>.tokens</code> format follows the W3C Design Tokens Community Group specification, making it potentially future proof for new and existing tools and platforms. It retains the JSON structure but enforces standardised keys and metadata.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"$schema"</span><span class="token operator">:</span> <span class="token string">"https://design-tokens.org/schema.json"</span><span class="token punctuation">,</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#007bff"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="consuming-different-file-formats" tabindex="-1">Consuming Different File Formats</h2>
<p>Let's look how Style Dictionary can consume these formats and what, if any, extra tools we need to install to compile your Design Tokens to your desired output files.</p>
<h3 id="natively-supported-formats" tabindex="-1">Natively Supported Formats</h3>
<p>Style Dictionary natively supports <code>.json</code> and <code>.tokens</code> 'out of the box'. As previously shown in earlier articles to have your Design Tokens generate an output format (CSS Custom Properties for example) you need to define the source and platform details:</p>
<h4 id="json" tabindex="-1">JSON</h4>
<pre class="language-javascript"><code class="language-javascript">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'tokens/**/*.json'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// No extra setup needed</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'color.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h4 id="w3c-.tokens" tabindex="-1">W3C <code>.tokens</code></h4>
<pre class="language-javascript"><code class="language-javascript">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'tokens/**/*.tokens'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// Works like JSON</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'border.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h3 id="custom-parser-formats" tabindex="-1">Custom Parser Formats</h3>
<p>To use a file format that is not supported natively you would need to install the relevant library and add a custom parser to the configuration file.</p>
<h4 id="yaml" tabindex="-1">YAML</h4>
<p>To install the YAML library</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> yaml</code></pre>
<p>We would then create a custom parser for it</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> yaml <span class="token keyword">from</span> <span class="token string">'yaml'</span><span class="token punctuation">;</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerParser</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'yaml-parser'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">pattern</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.ya?ml$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token function-variable function">parser</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> contents <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> yaml<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>contents<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>We can then use <code>.yaml</code> as the source in the configuration</p>
<pre class="language-javascript"><code class="language-javascript">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'tokens/**/*.yaml'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// YAML files</span>
  <span class="token literal-property property">parsers</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'yaml-parser'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'typography.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h3 id="json5" tabindex="-1">JSON5</h3>
<p>To install the JSON5 library.</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> json5</code></pre>
<p>We can then create a custom parser for it.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> json5 <span class="token keyword">from</span> <span class="token string">'json5'</span><span class="token punctuation">;</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerParser</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'json5-parser'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">pattern</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.json5$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token function-variable function">parser</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> contents <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> json5<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>contents<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Again, we can then setup our configuration file to consume <code>.json5</code> Design Token files</p>
<pre class="language-javascript"><code class="language-javascript">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'tokens/**/*.json5'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">parsers</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'json5-parser'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'spacing.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h3 id="hjson" tabindex="-1">HJSON</h3>
<p>To install the HJSON library.</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> hjson</code></pre>
<p>Again, we need to create a custom parser</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> hjson <span class="token keyword">from</span> <span class="token string">'hjson'</span><span class="token punctuation">;</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerParser</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'hjson-parser'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">pattern</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.hjson$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token function-variable function">parser</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> contents <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> hjson<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>contents<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Then, we can set up the configuration file to use <code>.hjson</code> files</p>
<pre class="language-javascript"><code class="language-javascript">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'tokens/**/*.hjson'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">parsers</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'hjson-parser'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'animation.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h2 id="bringing-it-all-together" tabindex="-1">Bringing it all together</h2>
<p>Not that I think you would or should decide to use multiple file formats to be consumed by Style Dictionary I think, for this article and example I'll tie all the options into a single config file.</p>
<p>If we have installed all the packages above we can then include them in our config file along with the custom parsers and also include these file formats as our possible sources:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> yaml <span class="token keyword">from</span> <span class="token string">'yaml'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> json5 <span class="token keyword">from</span> <span class="token string">'json5'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> hjson <span class="token keyword">from</span> <span class="token string">'hjson'</span><span class="token punctuation">;</span>

<span class="token comment">// Register custom parsers for YAML, JSON5, and HJSON</span>
StyleDictionary<span class="token punctuation">.</span><span class="token function">registerParser</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'yaml-parser'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">pattern</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.ya?ml$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token function-variable function">parser</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> contents <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> yaml<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>contents<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span><span class="token function">registerParser</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'json5-parser'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">pattern</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.json5$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token function-variable function">parser</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> contents <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> json5<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>contents<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

StyleDictionary<span class="token punctuation">.</span><span class="token function">registerParser</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'hjson-parser'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">pattern</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.hjson$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token function-variable function">parser</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> contents <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> hjson<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>contents<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Configure Style Dictionary</span>
<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.json</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token comment">// JSON (native)</span>
    <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.tokens</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token comment">// TOKENS (native)</span>
    <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.yaml</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token comment">// YAML (custom parser)</span>
    <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.json5</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token comment">// JSON5 (custom parser)</span>
    <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.hjson</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token comment">// HJSON (custom parser)</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">parsers</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'yaml-parser'</span><span class="token punctuation">,</span> <span class="token string">'json5-parser'</span><span class="token punctuation">,</span> <span class="token string">'hjson-parser'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// Custom parsers</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'all.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Build all platforms</span>
<span class="token keyword">await</span> myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Let's create a simple set of Design Tokens for each file format:</p>
<p><strong>color.json</strong></p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#007bff"</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#6c757d"</span> <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>border.tokens</strong></p>
<pre class="language-tokens"><code class="language-tokens">{
  "$schema": "https://design-tokens.org/schema.json",
  "border": {
    "radius": {
      "small": { "$value": "4px" },
      "large": { "$value": "8px" }
    }
  }
}</code></pre>
<p><strong>typography.yaml</strong></p>
<pre class="language-yaml"><code class="language-yaml"><span class="token key atrule">typography</span><span class="token punctuation">:</span>
  <span class="token key atrule">font</span><span class="token punctuation">:</span>
    <span class="token key atrule">family</span><span class="token punctuation">:</span>
      <span class="token key atrule">body</span><span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token key atrule">$value</span><span class="token punctuation">:</span> <span class="token string">'Roboto, sans-serif'</span> <span class="token punctuation">}</span>
      <span class="token key atrule">heading</span><span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token key atrule">$value</span><span class="token punctuation">:</span> <span class="token string">'Arial, sans-serif'</span> <span class="token punctuation">}</span>
    <span class="token key atrule">size</span><span class="token punctuation">:</span>
      <span class="token key atrule">small</span><span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token key atrule">$value</span><span class="token punctuation">:</span> <span class="token string">'0.875rem'</span> <span class="token punctuation">}</span>
      <span class="token key atrule">large</span><span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token key atrule">$value</span><span class="token punctuation">:</span> <span class="token string">'1.25rem'</span> <span class="token punctuation">}</span></code></pre>
<p><strong>spacing.json5</strong></p>
<pre class="language-json5"><code class="language-json5"><span class="token punctuation">{</span>
  <span class="token property unquoted">spacing</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property unquoted">none</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property unquoted">$value</span><span class="token operator">:</span> <span class="token string">'0'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property unquoted">small</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property unquoted">$value</span><span class="token operator">:</span> <span class="token string">'0.5rem'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property unquoted">medium</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property unquoted">$value</span><span class="token operator">:</span> <span class="token string">'1rem'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property unquoted">large</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property unquoted">$value</span><span class="token operator">:</span> <span class="token string">'2rem'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span></code></pre>
<p><strong>animation.hjson</strong></p>
<pre class="language-hjson"><code class="language-hjson">{
  animation: {
    duration: {
      short: { $value: "200ms" },
      medium: { $value: "500ms" },
      long: { $value: "1000ms" }
    }
  }
}</code></pre>
<p>When running the <code>build.js</code> file we will get a new CSS file containing all of these tokens as CSS custom properties:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/**
 * Do not edit directly, this file was auto-generated.
 */</span>

<span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-primary</span><span class="token punctuation">:</span> #007bff<span class="token punctuation">;</span>
  <span class="token property">--color-secondary</span><span class="token punctuation">:</span> #6c757d<span class="token punctuation">;</span>
  <span class="token property">--border-radius-small</span><span class="token punctuation">:</span> 4px<span class="token punctuation">;</span>
  <span class="token property">--border-radius-large</span><span class="token punctuation">:</span> 8px<span class="token punctuation">;</span>
  <span class="token property">--typography-font-family-body</span><span class="token punctuation">:</span> Roboto<span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
  <span class="token property">--typography-font-family-heading</span><span class="token punctuation">:</span> Arial<span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
  <span class="token property">--typography-font-size-small</span><span class="token punctuation">:</span> 0.875rem<span class="token punctuation">;</span>
  <span class="token property">--typography-font-size-large</span><span class="token punctuation">:</span> 1.25rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-none</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
  <span class="token property">--spacing-small</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-medium</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-large</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span>
  <span class="token property">--animation-duration-short</span><span class="token punctuation">:</span> 200ms<span class="token punctuation">;</span>
  <span class="token property">--animation-duration-medium</span><span class="token punctuation">:</span> 500ms<span class="token punctuation">;</span>
  <span class="token property">--animation-duration-long</span><span class="token punctuation">:</span> 1000ms<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>With the configuration and example tokens above, we’ve successfully demonstrated how to use different file formats to define design tokens and process them into a single output format.</p>
<p>This setup showcases the flexibility of Style Dictionary, enabling teams to choose the format that best suits their workflows while maintaining consistency in the output.</p>
<p>In the next part of this series, we’ll return to using <code>.json</code> as our design token format and dive into one of Style Dictionary’s most powerful features: automatic value transformations.</p>
<p>Style Dictionary allows you to define tokens in a single format, such as pixels (px), and then automatically convert them to other units based on your project’s needs. For example, you can set up tokens in px for mobile apps and have them automatically converted to rem for web development, ensuring consistent and accessible scaling.</p>
<p>We’ll also explore how these transformations can handle other use cases, like generating fallback colours for older browsers or converting colour formats from HEX to RGB. This flexibility reduces manual work and ensures your tokens are ready for use across multiple platforms. Stay tuned to see how these transformations can simplify and enhance your design token workflow!</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Creating A Generic Design System</title>
      <link href="https://www.alwaystwisted.com/articles/creating-a-generic-design-system.html"/>
      <updated>2024-11-18T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/creating-a-generic-design-system.html</id>
      <content type="html">
        <![CDATA[
        <p>In the last ~10 years of creating, updating, and building Design Systems as a front-end developer I've worked my way through a few possible solutions.</p>
<p>From building a simple component library using PHP, making use of Fractal, to helping build a customised documentation site using Eleventy … I have some thoughts.</p>
<p>The idea of creating a generic Design System that I can take with me for client work has always been something I've wanted to do, ever since working with a client 11 years ago and their pre-built themes for Sitecore CMS.</p>
<p>So, this is a start.</p>
<p>I've an idea on how I want to structure things, what languages I want to use and not use with the hope that I can create something that is useable and adaptable.</p>
<p>Of course, in reality, am I <em>relly</em> building a Design System or am I simply building another component library? We will see. I know I won't be creating anything in a design tool. I'm a front-end developer, I'll play to my strengths.</p>
<p>I do have grandiose ideas of streaming whilst I work on it. That might not come to fruition but I have decided to try and blog my way through it.</p>
<p>Naturally I've got a name for it. Mosaic.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Recently Closed Tabs - S01E01</title>
      <link href="https://www.alwaystwisted.com/articles/recently-closed-tabs-S01E01.html"/>
      <updated>2024-11-09T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/recently-closed-tabs-S01E01.html</id>
      <content type="html">
        <![CDATA[
        <p>I recently <a href="https://bsky.app/profile/sturobson.com/post/3laghd4htwv23">posted on Bluesky</a> about how I enjoyed Fridays on twitter in the past as a small group of people I followed would spend part of that day clearing out their open tabs from the week and sharing any juicy articles they found.</p>
<p>I followed this initial post with my opened tabs list that I read through, sharing the ones I found interesting.</p>
<p>I've decided to move this into a (potentially) weekly blog post too. It's 'just the links' no opinion, no summary. Simply a list of links I enjoyed reading. So here goes.</p>
<ul>
<li><a href="https://piccalil.li/blog/making-content-aware-components-using-css-has-grid-and-quantity-queries/">Making content-aware components using CSS :has(), grid, and quantity queries</a></li>
<li><a href="https://www.joshwcomeau.com/css/container-queries-introduction/">A Friendly Introduction to Container Queries</a></li>
<li><a href="https://medienbaecker.com/articles/focus-outlines">Beautiful focus outlines</a></li>
<li><a href="https://mayank.co/blog/css-reset-layer/">Your CSS reset should be layered</a></li>
<li><a href="https://hawkticehurst.com/2024/11/css-web-components-for-marketing-sites/">CSS Web Components for marketing sites</a></li>
<li><a href="https://heydonworks.com/article/the-button-element/">The Button Element</a></li>
<li><a href="https://css-tricks.com/come-to-the-light-dark-side/">Come to the light-dark() Side</a></li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Scaffolding Design System Components Using Plop.js</title>
      <link href="https://www.alwaystwisted.com/articles/scaffolding-design-system-components-using-plop-js.html"/>
      <updated>2024-11-01T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/scaffolding-design-system-components-using-plop-js.html</id>
      <content type="html">
        <![CDATA[
        <p>A tenet of Design Systems is a commitment to consistency, from creating and maintaining design tokens to standardising components and establishing uniform design patterns.</p>
<p>Creating a consistent folder structure with standardised files reinforces this principle, helping developers easily locate component files and understand their purpose. This repeatable structure reduces confusion, minimises onboarding time, and ensures that every component aligns with the system’s overall organisation and coding standards.</p>
<p>In this post, we’ll explore how to use plop.js to automate the creation of these files and folders, ensuring every component follows a consistent structure. We will walk through setting up plop.js, configuring templates, and creating prompts to streamline your workflow and keep your Design System and its components organised.</p>
<h2 id="what-is-plop.js%3F" tabindex="-1">What is plop.js?</h2>
<p><a href="https://plopjs.com/">Plop.js</a> is an open-source tool for automating file and folder creation, allowing us to generate consistent component structures with ease. By setting up templates and prompts, we can use plop.js to scaffold the necessary files for a component, ensuring everything follows our defined structure.</p>
<p>In this post, we will configure plop.js to generate the exact files and folders needed, making it simple to maintain consistency across all new components.</p>
<h2 id="setting-up-plop.js" tabindex="-1">Setting up plop.js</h2>
<p>To get us started, I have created a <a href="https://github.com/sturobson/component-scaffolding">new git repository which will have the finished code in</a>.</p>
<p>Let's begin by setting up the project with plop.js. After setting up the folder using <code>npm init</code> we need to install plop.js as a dependency</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> --save-dev plop</code></pre>
<p>Now create a configuration file <code>plopfile.js</code> that will be used to generate a component folder and files.</p>
<p>To start we need to add the basic configuration my importing plop</p>
<pre class="language-JavaScript"><code class="language-JavaScript">module.exports = (plop) => {
  // This is where we’ll define our component generator
};</code></pre>
<p>We can then define our generator. To start with we can give the generator a description, this is a helpful label especially if you plan to create several generators. If a user runs plop without specifying a generator it will display a list of generators available with these descriptions which can help the user understand the purpose of each option.</p>
<pre class="language-JavaScript"><code class="language-JavaScript">module.exports = (plop) => {
  plop.setGenerator('component', {
    description: 'Create a new component with files and folders',
  // more code</code></pre>
<p>As we are creating a generator for components we would need to ask the user the component name so it can generator appropriate files and folders with that name as needed:</p>
<pre class="language-JavaScript"><code class="language-JavaScript">module.exports = (plop) => {
  plop.setGenerator('component', {
    description: 'Create a new component with files and folders',
    prompts: [
      {
        type: 'input',
        name: 'name',
        message: 'Component name?',
      },
    ],
  // more code</code></pre>
<p>To start with let's generate an <code>.njk</code>, <code>.scss</code>, and <code>.js</code> file for the component. We can give the <code>.njk</code> file the component name that is inputted, the <code>.scss</code> and <code>.js</code> files will be both have the name of <code>index</code> so importing it simpler.</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@use</span> <span class="token string">'component-name'</span><span class="token punctuation">;</span>
<span class="token comment">// instead of</span>
<span class="token keyword">@use</span> <span class="token string">'component-name/component-name.scss'</span><span class="token punctuation">;</span></code></pre>
<p>For plop to create files we need to give the <code>plopfile.js</code> some actions, for this we are adding files so we use the type of <code>add</code>:</p>
<pre class="language-JavaScript"><code class="language-JavaScript">module.exports = (plop) => {
  plop.setGenerator('component', {
    description: 'Create a new component with files and folders',
    prompts: [
      {
        type: 'input',
        name: 'name',
        message: 'Component name?',
      },
    ],
    actions: [
      {
        type: 'add',
        path: 'src/components/{{pascalCase name}}/{{pascalCase name}}.njk'
      },
      {
        type: 'add',
        path: 'src/components/{{pascalCase name}}/index.scss'
      },
      {
        type: 'add',
        path: 'src/components/{{pascalCase name}}/index.js'
      },
    ],
  });
};</code></pre>
<h3 id="let's-generate" tabindex="-1">Let's Generate</h3>
<p>With a basic set of actions to create files in a folder we can start to use plop to scaffold new components. With the dependency installed we can add a build script to the <code>package.json</code>:</p>
<pre class="language-bash"><code class="language-bash"><span class="token string">"scripts"</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
  <span class="token string">"build"</span><span class="token builtin class-name">:</span> <span class="token string">"npm run plop"</span>,
  <span class="token string">"plop"</span><span class="token builtin class-name">:</span> <span class="token string">"plop component"</span>
<span class="token punctuation">}</span></code></pre>
<p>We can now run <code>npm run build</code> on the command line. This will give us a prompt:</p>
<p><img src="/images/articles/prompt-1.png" alt="a screenshot of terminal code where we have run 'npm run build' and are asked 'Component name?'" loading="lazy" decoding="async"></p>
<p>Giving the prompt a name and hitting return will generate the three files in a folder</p>
<p><img src="/images/articles/prompt-2.png" alt="a screenshot of terminal code where we have run 'npm run build' and are asked 'Component name? We have filled that out with 'button' and it shows that it has created three new files'" loading="lazy" decoding="async"></p>
<p>note: You can see in the <code>path</code> we have <code>{{pascalCase name}}</code>. <code>pascalCase</code> is here if you give the prompt more than one word for your component. I'm going to change this to <code>kebabCase</code> for the rest of this article.</p>
<h2 id="using-templates" tabindex="-1">Using Templates</h2>
<p>Each file generated using plop can have a associated Handlebars template file, ensuring consistent, structured content is created automatically during the plop process.</p>
<p>Let's say we want to have something like this in your generated Nunjucks and Sass files:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>class-name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@forward</span> <span class="token string">'config/variables'</span> <span class="token module-modifier keyword">as</span> *<span class="token punctuation">;</span>

<span class="token selector">.class-name </span><span class="token punctuation">{</span>
<span class="token punctuation">}</span></code></pre>
<p>We can create a new <code>.hbs</code> file for each of these and add the content needed so plop can generate them.</p>
<pre class="language-hbs"><code class="language-hbs"><span class="token block keyword">//</span> <span class="token variable">template</span><span class="token punctuation">/</span><span class="token variable">component</span><span class="token punctuation">.</span><span class="token variable">njk</span><span class="token punctuation">.</span><span class="token variable">hbs</span>

<span class="token punctuation">&lt;</span><span class="token variable">div</span> <span class="token variable">class</span><span class="token punctuation">=</span><span class="token string">'{{kebabCase name}}'</span><span class="token punctuation">></span>

<span class="token punctuation">&lt;</span><span class="token punctuation">/</span><span class="token variable">div</span><span class="token punctuation">></span></code></pre>
<pre class="language-hbs"><code class="language-hbs"><span class="token block keyword">//</span> <span class="token variable">template</span><span class="token punctuation">/</span><span class="token variable">index</span><span class="token punctuation">.</span><span class="token variable">scss</span><span class="token punctuation">.</span><span class="token variable">hbs</span> <span class="token punctuation">@</span><span class="token variable">use</span> <span class="token string">'config/variables'</span> <span class="token variable">as</span> <span class="token punctuation">*</span><span class="token punctuation">;</span> <span class="token punctuation">.</span><span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token variable">kebabCase</span> <span class="token variable">name</span><span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span></code></pre>
<p>We can reference these files in plopfile.js using templateFile:</p>
<pre class="language-JavaScript"><code class="language-JavaScript">module.exports = (plop) => {
  plop.setGenerator('component', {
    description: 'Create a new component with HTML and SCSS files',
    prompts: [
      {
        type: 'input',
        name: 'name',
        message: 'Component name?',
      },
    ],
    actions: [
      {
        type: 'add',
        path: 'components/{{kebabCase name}}/{{kebabCase name}}.njk',
        templateFile: 'plop-templates/component.njk.hbs',
      },
      {
        type: 'add',
        path: 'components/{{kebabCase name}}/index.scss',
        templateFile: 'plop-templates/index.scss.hbs',
      },
      {
        type: 'add',
        path: 'src/components/{{pascalCase name}}/index.js',
      },
    ],
  });
};</code></pre>
<h2 id="everything-is-a-component" tabindex="-1">Everything is a component</h2>
<p>When architecting the structure and naming conventions for your components you may find it easier to separate 'types of component' into separate folders. For example, if you use the ideas around <a href="https://bradfrost.com/blog/post/atomic-web-design/">Atomic Design</a> and want to follow the structure for your components as atoms, molecules, and organisms you may want to split out these types of components.</p>
<p>We can do this by adding a further prompt that can add a namespace to the component as well as put these components in the correct folder.</p>
<p>Adding another prompt that is a list will give the user only one option to pick which will aid consistency. Rather than requiring them to spell the type of token correctly or remember the name-spacing we can get the information from this prompt and generate the components folder and file structure accordingly.</p>
<p>Let's add a new prompt</p>
<pre class="language-JavaScript"><code class="language-JavaScript">{
  type: 'list',
  name: 'type',
  message: 'Is this component an atom, molecule, or organism?',
  choices: ['atom', 'molecule', 'organism'],
},</code></pre>
<p><img src="/images/articles/prompt-3.png" alt="a screenshot of terminal code where we have run 'npm run build' and are asked 'Component name?' After this it asks if the component is an atom, molecule, or organism, and gives us a list of those items to select" loading="lazy" decoding="async"></p>
<p>We still need to update the paths and any templates to make use of this prompt. The prompt gives us the <code>{{type}}</code> which takes the response from the <code>choices</code> in the prompt.</p>
<pre class="language-JavaScript"><code class="language-JavaScript">actions: [
  {
 type: 'add',
 path: 'components/{{type}}/{{type}}-{{kebabCase name}}/{{type}}-{{kebabCase name}}.njk',
 templateFile: 'plop-templates/component.njk.hbs',
  },
  {
 type: 'add',
 path: 'components/{{type}}/{{type}}-{{kebabCase name}}/index.scss',
 templateFile: 'plop-templates/index.scss.hbs',
  },
  {
 type: 'add',
 path: 'components/{{type}}/{{type}}-{{kebabCase name}}/index.js',
  },
],</code></pre>
<p><img src="/images/articles/prompt-4.png" alt="a screenshot of terminal code where we have run 'npm run build' and are asked 'Component name?' After this it asks if the component is an atom, molecule, or organism, and gives us a list of those items to select. Selecting atom - it creates three files" loading="lazy" decoding="async"></p>
<p>As you can see from the image we created a new component called <code>atoms-button</code>. The more mature your Design System becomes the more potential components you will had and may need to create. Rather than <code>atoms-</code>, <code>molecules-</code>, and <code>organisms-</code> as the name space, let's create a quick help that will abbreviate these to <code>a-</code>, <code>m-</code>, and <code>o-</code>.</p>
<pre class="language-JavaScript"><code class="language-JavaScript">// Custom helper to define type abbreviation
plop.setHelper('typeAbbreviation', (type) => {
  switch (type) {
    case 'atom': return 'a';
    case 'molecule': return 'm';
    case 'organism': return 'o';
    default: return '';
  }
});</code></pre>
<p>We still need to update the templates for the <code>.njk</code> and <code>.scss</code> file. So let's update the <code>plop-templates/component.njk.hbs</code> and <code>plop-templates/index.scss.hbs</code> files to make use of the <code>{{type}}</code> too.</p>
<pre class="language-hbs"><code class="language-hbs"><span class="token block keyword">//</span> <span class="token variable">template</span><span class="token punctuation">/</span><span class="token variable">component</span><span class="token punctuation">.</span><span class="token variable">njk</span><span class="token punctuation">.</span><span class="token variable">hbs</span>

<span class="token punctuation">&lt;</span><span class="token variable">div</span> <span class="token variable">class</span><span class="token punctuation">=</span><span class="token string">'{{typeAbbreviation type}}-{{kebabCase name}}'</span><span class="token punctuation">></span>

<span class="token punctuation">&lt;</span><span class="token punctuation">/</span><span class="token variable">div</span><span class="token punctuation">></span></code></pre>
<pre class="language-hbs"><code class="language-hbs"><span class="token block keyword">//</span> <span class="token variable">template</span><span class="token punctuation">/</span><span class="token variable">index</span><span class="token punctuation">.</span><span class="token variable">scss</span><span class="token punctuation">.</span><span class="token variable">hbs</span> <span class="token punctuation">@</span><span class="token variable">use</span> <span class="token string">'config/variables'</span> <span class="token variable">as</span> <span class="token punctuation">*</span><span class="token punctuation">;</span> <span class="token punctuation">.</span><span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token variable">typeAbbreviation</span>
  <span class="token variable">type</span>
<span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token variable">-</span><span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token variable">kebabCase</span> <span class="token variable">name</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
<span class="token punctuation">{</span> <span class="token punctuation">}</span></code></pre>
<p><img src="/images/articles/prompt-5.png" alt="a screenshot of terminal code where we have run 'npm run build' and are asked 'Component name?' After this it asks if the component is an atom, molecule, or organism, and gives us a list of those items to select. Selecting atom - it creates three files. This time the atoms is abbreviated to a- for the component files and folder name" loading="lazy" decoding="async"></p>
<h2 id="what-else-to-generate-for-a-design-systems-component" tabindex="-1">What else to generate for a Design Systems component</h2>
<p>No we have a basic component folder and file structure generator we can think of what else we might need.</p>
<h3 id="a-read-me-file" tabindex="-1">a read me file</h3>
<pre class="language-JavaScript"><code class="language-JavaScript">{
  type: 'add',
  path: 'src/components/{{type}}s/{{typeAbbreviation type}}-{{kebabCase name}}/README.md',
  templateFile: 'plop-templates/README.md.hbs',
}</code></pre>
<h3 id="adding-a-creation-date" tabindex="-1">adding a creation date</h3>
<p>Creating a new helper we can add a 'creation date' to files we need to:</p>
<pre class="language-JavaScript"><code class="language-JavaScript">  plop.setHelper('creationDate', () => new Date().toLocaleDateString());</code></pre>
<p>Which could be used in the README.md template:</p>
<pre class="language-handlebars"><code class="language-handlebars"><span class="token handlebars language-handlebars"><span class="token delimiter punctuation">{{</span><span class="token variable">typeAbbreviation</span> <span class="token variable">type</span><span class="token delimiter punctuation">}}</span></span>-<span class="token handlebars language-handlebars"><span class="token delimiter punctuation">{{</span><span class="token variable">kebabCase</span> <span class="token variable">name</span><span class="token delimiter punctuation">}}</span></span>
Documentation Created on:
<span class="token handlebars language-handlebars"><span class="token delimiter punctuation">{{</span><span class="token variable">creationDate</span><span class="token delimiter punctuation">}}</span></span>

--- ## Usage ## Code Example ## Variants ## Props</code></pre>
<h2 id="" tabindex="-1"></h2>
<p>By making use of <code>plop.js</code> we have automated a consistent structure for our component files, helping maintain organisation and clarity in our codebase. This initial setup can be easily adapted to your differing projects. You might consider adding test files, component design tokens <code>.json</code>, moving Sass into a separate folder. Adjusting <code>plop.js</code> to match your team's needs and workflow are simple with the flexibility it offers.</p>
<p>I hope this short tutorial has helped you think about a practical approach to enhancing your Design System's scalability and efficiency by automating a small part.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 2) - Outputting to Different Formats with Style Dictionary</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-2.html"/>
      <updated>2024-10-31T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-2.html</id>
      <content type="html">
        <![CDATA[
        <p>In the first tutorial in this series I walked us through creating up a simple Style Dictionary setup that can transform your Design Tokens (in <code>.json</code>) to different formats (a <code>.css</code> file of CSS Custom Properties and Sass variables in a <code>.scss</code> file). In this tutorial we will go through the other 'built-in' formats that are available, how to set them up, what they are for, and what they would look like.</p>
<h2 id="defining-design-tokens" tabindex="-1">Defining Design Tokens</h2>
<p>Let's look again at the Design Tokens from the first part in this series. We have a couple of colours, some spacing units, and some typography decisions.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
    <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#007bff"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#6c757d"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"spacing"</span><span class="token punctuation">,</span>
    <span class="token property">"none"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"0"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"small"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"0.5rem"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"medium"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1rem"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"typography"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"font"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"family"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span><span class="token punctuation">,</span>
        <span class="token property">"body"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Roboto, sans-serif"</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"size"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontSize"</span><span class="token punctuation">,</span>
        <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1rem"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"lg"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1.25rem"</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="built-in-formats" tabindex="-1">Built In Formats</h2>
<p>Out of the box Style Dictionary comes with several built-in formats you can use to convert your Design Tokens from <code>.json</code> to a file format that can be used with various platforms and codebases.</p>
<p>There are formats for CSS, Sass, LESS, Stylus, JavaScript, TypeScript, Android, iOS, Swift, and JSON. With all these possibilities we can truly keep design decisions in sync across the various platforms we need to. This also allows you to scale to new codebases more easily because the Design Token <code>.json</code> stays the same but can output to what you need, as needed.</p>
<p>Let's go through a couple of them to see what how we can turn our Design Tokens into useable code for our projects. You can follow along and <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/02-Different-Formats">see the results in the fresh branch of the git repository</a>.</p>
<h3 id="css" tabindex="-1">CSS</h3>
<p>We've already seen this in <a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-1">the first article</a>. The format <code>css/variables</code> takes the <code>.json</code> and creates a <code>.css</code> with the Design Tokens generated as CSS Custom Properties.</p>
<h3 id="css-preprocessors" tabindex="-1">CSS Preprocessors</h3>
<h4 id="sass" tabindex="-1">Sass</h4>
<h5 id="variables" tabindex="-1">Variables</h5>
<p>Again, from the first article. The format <code>scss/variables</code> can create a file of Sass variables based on the Design Tokens in the <code>.scss</code> format.</p>
<h5 id="map-(flat)" tabindex="-1">Map (flat)</h5>
<p>Using the format <code>scss/map-flat</code> provides a Sass map of the Design Tokens. To incorporate this into the example git repository we need to add some additional code to the <code>build.js</code> file.</p>
<p>We can add this to the existing <code>scss</code> platform in <code>build.js</code>. Platforms in Style Dictionary define the different output formats where you want your Design Tokens to be used. Each platform has unique configurations for how the tokens are to be transformed, formmated, and written to files.</p>
<p>To add a flat Sass Map to our project we need to add a new destination for where the file is created and tell Style Dictionary what format to use. We can do this by adding:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token punctuation">{</span>
  <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'tokens-map.scss'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'scss/map-flat'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span></code></pre>
<p>After the existing destination and format for <code>scss/variabkes</code>. The complete file would look like this:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.json</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/css/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'variables.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">scss</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'scss'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/scss/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'_variables.scss'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'scss/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'tokens-map.scss'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'scss/map-flat'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Once we build the tokens again we will get a new <code>tokens-map.scss</code> file withe the following content:</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$tokens</span></span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
  <span class="token string">'color-primary'</span><span class="token punctuation">:</span> #007bff<span class="token punctuation">,</span>
  <span class="token string">'color-secondary'</span><span class="token punctuation">:</span> #6c757d<span class="token punctuation">,</span>
  <span class="token string">'spacing-none'</span><span class="token punctuation">:</span> 0<span class="token punctuation">,</span>
  <span class="token string">'spacing-small'</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">,</span>
  <span class="token string">'spacing-medium'</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">,</span>
  <span class="token string">'typography-font-family-body'</span><span class="token punctuation">:</span> Roboto<span class="token punctuation">,</span>
  sans-serif<span class="token punctuation">,</span>
  <span class="token string">'typography-font-size-base'</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">,</span>
  <span class="token string">'typography-font-size-lg'</span><span class="token punctuation">:</span> 1.25rem<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h5 id="map-(deep)" tabindex="-1">Map (deep)</h5>
<p>We can use the Style Dictionary format <code>scss/map-deep</code> to generate a list of Sass variables and then a nested Sass map that references them.</p>
<p>Again, we can add the new format and destination to our <code>build.js</code> file to then have Style Dictionary create a new <code>.scss</code> file with variables and map.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token punctuation">{</span>
  destination<span class="token operator">:</span> <span class="token string">'tokens-map-deep.scss'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'scss/map-deep'</span><span class="token punctuation">,</span>  <span class="token comment">// Deep map format</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span></code></pre>
<p>Getting Style Dictionary to generate the various files will now create this new Sass file which would look like this:</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$color-primary</span></span><span class="token punctuation">:</span> #007bff <span class="token statement keyword">!default</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$color-secondary</span></span><span class="token punctuation">:</span> #6c757d <span class="token statement keyword">!default</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-none</span></span><span class="token punctuation">:</span> 0 <span class="token statement keyword">!default</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-small</span></span><span class="token punctuation">:</span> 0.5rem <span class="token statement keyword">!default</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-medium</span></span><span class="token punctuation">:</span> 1rem <span class="token statement keyword">!default</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$typography-font-family-body</span></span><span class="token punctuation">:</span> Roboto<span class="token punctuation">,</span> sans-serif <span class="token statement keyword">!default</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$typography-font-size-base</span></span><span class="token punctuation">:</span> 1rem <span class="token statement keyword">!default</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$typography-font-size-lg</span></span><span class="token punctuation">:</span> 1.25rem <span class="token statement keyword">!default</span><span class="token punctuation">;</span>

<span class="token property"><span class="token variable">$tokens</span></span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
  <span class="token string">'color'</span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
    <span class="token string">'primary'</span><span class="token punctuation">:</span> <span class="token variable">$color-primary</span><span class="token punctuation">,</span>
    <span class="token string">'secondary'</span><span class="token punctuation">:</span> <span class="token variable">$color-secondary</span><span class="token punctuation">,</span>
  <span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token string">'spacing'</span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
    <span class="token string">'none'</span><span class="token punctuation">:</span> <span class="token variable">$spacing-none</span><span class="token punctuation">,</span>
    <span class="token string">'small'</span><span class="token punctuation">:</span> <span class="token variable">$spacing-small</span><span class="token punctuation">,</span>
    <span class="token string">'medium'</span><span class="token punctuation">:</span> <span class="token variable">$spacing-medium</span><span class="token punctuation">,</span>
  <span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token string">'typography'</span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
    <span class="token string">'font'</span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
      <span class="token string">'family'</span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
        <span class="token string">'body'</span><span class="token punctuation">:</span> <span class="token variable">$typography-font-family-body</span><span class="token punctuation">,</span>
      <span class="token punctuation">)</span><span class="token punctuation">,</span>
      <span class="token string">'size'</span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
        <span class="token string">'base'</span><span class="token punctuation">:</span> <span class="token variable">$typography-font-size-base</span><span class="token punctuation">,</span>
        <span class="token string">'lg'</span><span class="token punctuation">:</span> <span class="token variable">$typography-font-size-lg</span><span class="token punctuation">,</span>
      <span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="javascript-and-typescript" tabindex="-1">JavaScript and TypeScript</h3>
<p>Style Dictionary has 3 JavaScript and 1 TypeScript built-in formats that can be used to generate various forms of JavaScript for various needs and projects.</p>
<h4 id="javascript-(object)" tabindex="-1">JavaScript (Object)</h4>
<p>Using the format <code>javascript/object</code> will export the tokens as a structured JavaScript object using the hierarchy defined in the Design Tokens. These can be used in your Vue or React projects that make use of direct JavaScript imports. In React, for example, you can import the tokens and apply them directly within a CSS-in-JS solution (like styled-components).</p>
<p>To add a JavaScript format to our existing <code>build.js</code> file we will als need to include a new platform (<code>js</code>) so Style Dictionary knows what to do when generating the code.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token literal-property property">js</span><span class="token operator">:</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'js'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/js/'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
 <span class="token punctuation">{</span>
   <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'tokens.js'</span><span class="token punctuation">,</span>
   <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'javascript/object'</span><span class="token punctuation">,</span>
 <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span></code></pre>
<p>This will then generate a JavaScript file of the tokens like this (I've also popped this into a <code>js</code> folder to try to keep the build folder a little cleaner):</p>
<pre class="language-JavaScript"><code class="language-JavaScript">var _styleDictionary = {
  "color": {
    "primary": {
      "$value": "#007bff",
      "filePath": "src/tokens/tokens.json",
      "isSource": true,
      "$type": "color",
      "original": {
        "$value": "#007bff",
        "$type": "color"
      },
      "name": "ColorPrimary",
      "attributes": {
        "category": "color",
        "type": "primary"
      },
      "path": [
        "color",
        "primary"
      ]
    },
  // more code followed</code></pre>
<h4 id="javascript-(module-flat)" tabindex="-1">JavaScript (Module Flat)</h4>
<p>This built-in format creates a file of flat JavaScript objects. This could be great for projects that need to access tokens frequently and directly, without needing to navigate the structure of the Design Tokens to get to it. This flat output may also be better for projects that use a JavaScript bundler. A flat object also aligns more closely with how Design Tokens can be 'directly' in CSS or Sass as Custom Properties and Variables.</p>
<p>Adding the below to the <code>files</code> within our <code>js</code> platform in the <code>build.js</code> file:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token punctuation">{</span>
  <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'tokens-flat.js'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'javascript/module-flat'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span></code></pre>
<p>Will give us the flat JavaScript objects:</p>
<pre class="language-JavaScript"><code class="language-JavaScript">module.exports = {
  "ColorPrimary": "#007bff",
  "ColorSecondary": "#6c757d",
  "SpacingNone": "0",
  "SpacingSmall": "0.5rem",
  "SpacingMedium": "1rem",
  "TypographyFontFamilyBody": "Roboto, sans-serif",
  "TypographyFontSizeBase": "1rem",
  "TypographyFontSizeLg": "1.25rem"
};</code></pre>
<h4 id="javascript-(umd)" tabindex="-1">JavaScript (UMD)</h4>
<p>Generating a <code>.js</code> file using this format could allow tokens to be accessed as global variables when CommonJS or AMD imports are not available. This could work well for older or mixed environments where some flexibility is key. This format can be particularly handy in environments that cannot guarantee ES module support.</p>
<p>Adding the new <code>destionation</code> and <code>format</code>:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token punctuation">{</span>
  <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'tokens-umd.js'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'javascript/umd'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span></code></pre>
<p>Will generate a JavaScript file that looks like this which includes the Universal Module Definition wrapper to make sure the code inside can be used in multiple environments:</p>
<pre class="language-JavaScript"><code class="language-JavaScript">(function(root, factory) {
  if (typeof module === "object" && module.exports) {
    module.exports = factory();
  } else if (typeof exports === "object") {
    exports["_styleDictionary"] = factory();
  } else if (typeof define === "function" && define.amd) {
    define([], factory);
  } else {
    root["_styleDictionary"] = factory();
  }
}(this, function() {
  return {
  "color": {
    "primary": {
      "$value": "#007bff",
      "filePath": "src/tokens/tokens.json",
      "isSource": true,
      "$type": "color",
      "original": {
        "$value": "#007bff",
        "$type": "color"
      },
      "name": "ColorPrimary",
      "attributes": {
        "category": "color",
        "type": "primary"
      },
      "path": [
        "color",
        "primary"
      ]
    },</code></pre>
<h4 id="typescript-(es6-declarations)" tabindex="-1">TypeScript (ES6 Declarations)</h4>
<p>This format creates a <code>.d.ts</code> file of your Design Tokens to provide TypeScript definitions so that TypeScript projects can use the tokens with type safety and autocomplete support. This does not output the actual token values but instead provides types, ensuring that TypeScript can recognise and check token names and types within code.</p>
<p>Let's add a new platform for TypeScript to our <code>build.js</code> file to generate the <code>.d.ts</code> file:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token literal-property property">ts</span><span class="token operator">:</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'js'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/types/'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
 <span class="token punctuation">{</span>
   <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'tokens.d.ts'</span><span class="token punctuation">,</span>
   <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'typescript/es6-declarations'</span><span class="token punctuation">,</span>
 <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span></code></pre>
<p>This will generate:</p>
<pre class="language-TypeScript"><code class="language-TypeScript">export const ColorPrimary : string;
export const ColorSecondary : string;
export const SpacingNone : string;
export const SpacingSmall : string;
export const SpacingMedium : string;
export const TypographyFontFamilyBody : string;
export const TypographyFontSizeBase : string;
export const TypographyFontSizeLg : string;</code></pre>
<h3 id="android" tabindex="-1">Android</h3>
<p>Using <code>android/resources</code> will generate an XML resource file containing the Design Tokens that follows Android's resource naming conventions.</p>
<p>We will need to define a new platform in our <code>build.js</code> file and add the relevant <code>destination</code> and <code>format</code> so Style Dictionary can generate the XML file correctly:</p>
<pre class="language-JavaScript"><code class="language-JavaScript">android: {
  transformGroup: 'android',
  buildPath: 'build/android/',
  files: [
 {
   destination: 'values/tokens.xml',
   format: 'android/resources',
 },
  ],
},</code></pre>
<p>This will generate a file of mixed types within a single <code>&lt;resources&gt;</code> tag for Android development:</p>
<pre class="language-xml"><code class="language-xml"><span class="token prolog">&lt;?xml version="1.0" encoding="UTF-8"?></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>resources</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>color</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>color_primary<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>#ff007bff<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>color</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>color</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>color_secondary<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>#ff6c757d<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>color</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>string</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_none<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>0<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>string</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>string</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_small<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>0.5rem<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>string</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>string</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>spacing_medium<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>1rem<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>string</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>string</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>typography_font_family_body<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Roboto, sans-serif<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>string</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dimen</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>typography_font_size_base<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>16.00sp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dimen</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dimen</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>typography_font_size_lg<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>20.00sp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dimen</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>resources</span><span class="token punctuation">></span></span></code></pre>
<h3 id="ios-%2F-swift" tabindex="-1">iOS / Swift</h3>
<h4 id="ios-swift-(class)" tabindex="-1">iOS Swift (class)</h4>
<p>This <code>format</code> will create a Swift class file that defines the Design Tokens as static properties which can be directly accessed within iOS code ideal when you need to use Design Tokens as constants throughout the codebase.</p>
<p>Again, we will need to define a new platform in our <code>build.js</code> file for this format:</p>
<pre class="language-JavaScript"><code class="language-JavaScript">ios: {
  transformGroup: 'ios-swift',
  buildPath: 'build/ios/',
  files: [
 {
   destination: 'Tokens.swift',
   format: 'ios-swift/class.swift',
   className: 'Tokens', // Name of the Swift class
 },
  ],
},</code></pre>
<p>When run the <code>build.js</code> file will then create a new file in <code>build/ios/</code> called <code>Tokens.swift</code> with the following:</p>
<pre class="language-swift"><code class="language-swift"><span class="token keyword">import</span> <span class="token class-name">UIKit</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> colorPrimary <span class="token operator">=</span> <span class="token class-name">UIColor</span><span class="token punctuation">(</span>red<span class="token punctuation">:</span> <span class="token number">0.000</span><span class="token punctuation">,</span> green<span class="token punctuation">:</span> <span class="token number">0.482</span><span class="token punctuation">,</span> blue<span class="token punctuation">:</span> <span class="token number">1.000</span><span class="token punctuation">,</span> alpha<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> colorSecondary <span class="token operator">=</span> <span class="token class-name">UIColor</span><span class="token punctuation">(</span>red<span class="token punctuation">:</span> <span class="token number">0.424</span><span class="token punctuation">,</span> green<span class="token punctuation">:</span> <span class="token number">0.459</span><span class="token punctuation">,</span> blue<span class="token punctuation">:</span> <span class="token number">0.490</span><span class="token punctuation">,</span> alpha<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> spacingMedium <span class="token operator">=</span> 1rem
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> spacingNone <span class="token operator">=</span> <span class="token number">0</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> spacingSmall <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">.</span>5rem
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> typographyFontFamilyBody <span class="token operator">=</span> <span class="token class-name">Roboto</span><span class="token punctuation">,</span> sans<span class="token operator">-</span>serif
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> typographyFontSizeBase <span class="token operator">=</span> <span class="token class-name">CGFloat</span><span class="token punctuation">(</span><span class="token number">16.00</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">let</span> typographyFontSizeLg <span class="token operator">=</span> <span class="token class-name">CGFloat</span><span class="token punctuation">(</span><span class="token number">20.00</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>Going through the above built-in formats only shows an example of what is possible 'out of the box'. There are also built-in formats for the Less and Stylus CSS preprocessors, for various outputs of JSON, and a few more options for iOS and Swift.</p>
<p>Having all these options means you have the ability to push your Design Tokens across teams, projects, and platforms and create consistency and trust in your products. Using Design Tokens as a source of truth for your design decisions can also help streamline development and updates.</p>
<p>These are 'built-in' formats which means we can also create our own custom formats, for example, with <code>scss/map-deep</code> I would want a separate <code>.scss</code> file for my Sass variables and then have the map in a different file rather than a single file with both.</p>
<p>While Style Dictionary’s built-in formats cover a wide range, customisation is often essential.</p>
<p>In a future article, we’ll look into how to create custom formats tailored to your unique needs. Whether you need to separate variables from maps in Sass or define specialised token structures, custom formats will allow you to adapt Style Dictionary even further to fit your project.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Weeknotes S01E01</title>
      <link href="https://www.alwaystwisted.com/articles/weeknotes-S01E01.html"/>
      <updated>2024-10-25T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/weeknotes-S01E01.html</id>
      <content type="html">
        <![CDATA[
        <p>I'm not sure if I'll remember to do this regularly, but I'm hoping that the bare bones of a new setup in Obsidian will have me making notes during the week to collate on a Friday.</p>
<h2 id="writing" tabindex="-1">Writing</h2>
<p>This week I wrote 3 new articles (not including this week note):</p>
<p><a href="https://www.alwaystwisted.com/articles/creating-design-system-friendly-snowflakes-with-utility-classes.html">Creating Design System-Friendly Snowflakes with Utility Classes</a></p>
<p><a href="https://www.alwaystwisted.com/articles/what-else-can-we-do-with-design-tokens.html">What Else Can We Do With Design Tokens?</a></p>
<p><a href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-1.html">A Design Tokens Workflow (part 1) - Getting Started With Style Dictionary</a></p>
<p>I've done a few tweaks to the website, I've removed the 'yellow' colour theme option as it only really worked in dark mode and I didn't want to do something for one theme. Six colour themes is more than enough 😭.</p>
<h2 id="looking-for-work" tabindex="-1">Looking For Work</h2>
<p>Oh yes, I'm still looking for work. Todays task after publishing this is to get 'into the weeds' of what services I can provide.</p>
<p>Although I am more than happy to join existing teams in creating or maintaining their design system and helping agencies in turning around designs into front-end code I'm looking at shorter, focused services I can provide.</p>
<p>If you think you've got a project in mind, <a href="mailto:hire@sturobson.com">let's chat</a>.</p>
<h2 id="watched" tabindex="-1">Watched</h2>
<p>I don't know if it's (more often than not) because of the ability to 'binge watch' series or if there's actually been a 'drought' of good content we can watch at the end of the day.</p>
<p>Although we're nearing the finale of 'Spooky Season' my partner isn't a fan of the horror genre my chances to watch this years tranche of halloween horror is pretty slim.</p>
<h3 id="sweetpea" tabindex="-1">Sweetpea</h3>
<p>We watched Sweetpea, we both enjoyed it. Not to give any spoilers, we're looking forward to series two already.</p>
<h3 id="fl.-vs-boone" tabindex="-1">FL. vs Boone</h3>
<p>I don't remember how I came to it - but I've been watching several Live Courts from the US via <a href="https://www.youtube.com/@TheEmilyDBaker">Emily D. Bakers YouTube Channel</a>. It started about a third of the way through Depp v. Heard and I've just stayed with the live streams either in the background or for a short period before bed.</p>
<h3 id="woman-of-the-hour" tabindex="-1">Woman Of The Hour</h3>
<p>Based on the true story of <a href="https://en.wikipedia.org/wiki/Rodney_Alcala">The Dating Game Killer</a> and a directorial debut from <a href="https://en.wikipedia.org/wiki/Anna_Kendrick">Anna Kendrick</a> who plays the lead - I really enjoyed the look of this when it was 'on the set' of the game show. The treatment to those scenes felt more real to me than <a href="https://www.imdb.com/title/tt14966898/">Late Night With The Devil</a> which I believe was let down by the black and white scenes looking too 'new'. Going into this I didn't know it was based on a 'true crime' story. I enjoyed it.</p>
<h2 id="read" tabindex="-1">Read</h2>
<p>I haven't read much this week, the current book on the Kindle is <a href="https://www.goodreads.com/book/show/64623481-the-september-house">The September House</a> but I don't think I've managed to read a word.</p>
<h2 id="listened" tabindex="-1">Listened</h2>
<h3 id="podcasts" tabindex="-1">Podcasts</h3>
<p>I've a vague memory of watching Halloween on an old black and white TB, late at night with the contrast down so the images on the screen were dark grey on black. I think this was the start of me becoming a fan of the horror genre.</p>
<p>I don't listen to many podcasts, there's a couple of Design Systems-related ones and the odd true crime series but I do look out for an interesting episode of <a href="https://podcasts.bloody-disgusting.com/#horrorqueers">Horror Queers</a>.</p>
<p>This weeks was a two hour dive into Black Christmas from 1974. Coming out before Halloween, there's still bits that make me jump. This film (and it's 2019 remake (but not the 2006 remake)) are always on my Christmas/Horror watch list.</p>
<h3 id="music" tabindex="-1">Music</h3>
<p>Did you know that The Smashing Pumpkins released - Mellon Collie and the Infinite Sadness - a whole day earlier in the UK compared to the rest of the world‽ Did you know it turned 29 years old?</p>
<p>This album came out in my first year of A-Levels - a perfect sound track to the next two years. I also managed to snag a ticket to see them in the tin shed that is/was(?) Wembley Arena on the tour.</p>
<p>I had a look on Spotyify at the number of plays per track and it seems not many folks listened to the second of this double album.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Design Tokens Workflow (part 1) - Getting Started With Style Dictionary</title>
      <link href="https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-1.html"/>
      <updated>2024-10-24T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-design-tokens-workflow-part-1.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="what-are-design-tokens" tabindex="-1">What are Design Tokens</h2>
<p>Design Tokens have become a widely-adopted method to store design decisions (such as colours, typography, spacing, border-radius, and other visual properties) across products, applications, and websites.</p>
<p>They help create a shared language between design and development (and beyond), ensuring consistency across a digital product’s design and implementation.</p>
<p>By converting these design decisions into platform-specific formats (like CSS variables for the web or XML for Android), design tokens ensure that your visual guidelines are accurately applied no matter where they are used.</p>
<p>To do this efficiently, we can use tools that automate the process. <a href="https://v4.styledictionary.com">Style Dictionary</a> is one popular open-source tool that can be used to take Design Tokens in a <code>.json</code> format and generate relevant, specific files for your needs. There are also other tools, such as Theo, Thing1, Thing2, and Thing3.</p>
<p>In this tutorial, and for future tutorials in the series, I'll be using Style Dictionary. I have created a <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/01-Getting-Started">git repository</a> that will include the end results.</p>
<h2 id="initial-setup" tabindex="-1">Initial setup</h2>
<p>To get started, you’ll need to install Style Dictionary. It can either be installed globally:</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> <span class="token parameter variable">-g</span> style-dictionary</code></pre>
<p>Or it can be installed as a dependency of your project. It is most likely that you would install Style Dictionary this way:</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> <span class="token parameter variable">-D</span> style-dictionary</code></pre>
<p>We can create a new folder (project) and open it with our text editor to get started.</p>
<p>As we will be using <a href="https://www.npmjs.com">npm</a> we will need to initialise this in the project and fill out any relevant questions posed in the terminal.</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> init</code></pre>
<p>We should then have a new <code>package.json</code> and <code>package-lock.json</code> file. The <code>package.json</code> file could look something like this:</p>
<pre class="language-bash"><code class="language-bash"><span class="token punctuation">{</span>
  <span class="token string">"name"</span><span class="token builtin class-name">:</span> <span class="token string">"style-dictionary-starter"</span>,
  <span class="token string">"version"</span><span class="token builtin class-name">:</span> <span class="token string">"0.1.0"</span>,
  <span class="token string">"devDependencies"</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
    <span class="token string">"style-dictionary"</span><span class="token builtin class-name">:</span> <span class="token string">"^4.1.4"</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="creating-a-build-script" tabindex="-1">Creating a build script</h3>
<p>To get Style Dictionary to create the files we need we need to create a build script. To start with in this series we are going to have a small set of example Design Tokens in <code>.json</code> that we are going to use to create a CSS file of CSS custom properties.</p>
<p>Here's the full build script:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.json</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'variables.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">await</span> myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Let's go through this, line by line to see what the script is doing.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span></code></pre>
<p>Imports Style Dictionary to process tokens.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span></code></pre>
<p>Creates a new instance of StyleDictionary using a configuration object which will handle the processing and building of the design tokens based on the provided settings.</p>
<pre class="language-js"><code class="language-js"><span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span>src<span class="token operator">/</span>tokens<span class="token comment">/**/</span><span class="token operator">*</span><span class="token punctuation">.</span>json<span class="token punctuation">]</span><span class="token punctuation">,</span></code></pre>
<p>Specifies the location of the design token files. The pattern <code>**/*.json</code> tells Style Dictionary to look for any <code>.json</code> files in the directory and its sub directories.</p>
<pre class="language-js"><code class="language-js"><span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span></code></pre>
<p>Begins the configuration for different platforms. Each platform defines how and where the design tokens should be transformed and outputted to.</p>
<pre class="language-js"><code class="language-js"><span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span></code></pre>
<p>Defines a platform named css. This platform will transform the design tokens into a format suitable for CSS usage.</p>
<pre class="language-js"><code class="language-js"><span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span></code></pre>
<p>Specifies the transform group css. This group tells Style Dictionary to use a set of predefined transforms that convert tokens to CSS-compatible values.</p>
<pre class="language-js"><code class="language-js"><span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/'</span><span class="token punctuation">,</span></code></pre>
<p>Sets the output directory to build/. The processed files generated by Style Dictionary will be placed in this directory.</p>
<pre class="language-js"><code class="language-js"><span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
 <span class="token punctuation">{</span>
  <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'variables.css'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
 <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span></code></pre>
<p>This array defines the files that will be generated. Each object in this array represents a separate output file. This specific object configures a file named <code>variables.css</code>:</p>
<pre class="language-js"><code class="language-js"><span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'variables.css'</span><span class="token punctuation">,</span></code></pre>
<p>Sets the file name.</p>
<pre class="language-js"><code class="language-js"><span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span></code></pre>
<p>This tells Style Dictionary to convert the design tokens into CSS custom properties.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">await</span> myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Asynchronously builds the design tokens for all defined platforms. In this example, it processes the tokens and generates the <code>variables.css</code> file in the <code>build/</code> directory based on the configuration provided.</p>
<h3 id="updating-our-package.json" tabindex="-1">Updating our <code>package.json</code></h3>
<p>We can then add a <code>&quot;build&quot;: &quot;node build.js&quot;</code> to the <code>package.json</code> to allow us to use the command <code>npm run build</code> to run Style Dictionary and build out the files specified.</p>
<pre class="language-bash"><code class="language-bash"><span class="token punctuation">{</span>
  <span class="token string">"name"</span><span class="token builtin class-name">:</span> <span class="token string">"style-dictionary-starter"</span>,
  <span class="token string">"version"</span><span class="token builtin class-name">:</span> <span class="token string">"0.1.0"</span>,
  <span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"module"</span>,
  <span class="token string">"scripts"</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
    <span class="token string">"build"</span><span class="token builtin class-name">:</span> <span class="token string">"node build.js"</span>
  <span class="token punctuation">}</span>,
  <span class="token string">"devDependencies"</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
    <span class="token string">"style-dictionary"</span><span class="token builtin class-name">:</span> <span class="token string">"^4.1.4"</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="creating-some-tokens" tabindex="-1">Creating some tokens</h2>
<p>Running <code>npm run build</code> now runs the <code>build.js</code> code but we do not get a <code>variables.css</code> file in the <code>build</code> folder because we haven't created any <code>.json</code> files.</p>
<p>Here is an example to demonstrate how to structure Design tokens in <code>.json</code>.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
    <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#007bff"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#6c757d"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"spacing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"spacing"</span><span class="token punctuation">,</span>
    <span class="token property">"none"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"0"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"small"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"0.5rem"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"medium"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1rem"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"typography"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"font"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"family"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span><span class="token punctuation">,</span>
        <span class="token property">"body"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Roboto, sans-serif"</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token property">"size"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontSize"</span><span class="token punctuation">,</span>
        <span class="token property">"base"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1rem"</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">"lg"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"1.25rem"</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>In this example we are defining tokens for colour, spacing and typography. Style Dictionary will traverse the file and create CSS custom properties following the tree in the <code>.json</code>.</p>
<p>You will notice that I am including a <code>$type</code> for each, or each group of tokens. Using <code>$type</code> tells Style Dictionary what kind of value it is dealing with allowing it to apply any built-in transformations (for example, a <code>color</code> token can undergo a conversion from the HEX value that is written to an RGB value if instructed to). Adding <code>$type</code> can also create consistent formatting across platforms, it can be used in validation and error handling, it can also be used if you define any custom transformations, like converting the <code>fontWeight</code> from <code>400</code> to <code>regular</code> if you needed it to.</p>
<p>When running <code>npm run build</code> which runs the <code>build.js</code> file Style Dictionary will create <code>--color-primary: #007bff;</code> from the following.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
    <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#007bff"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>The full <code>variables.css</code> file will be outputted to this:</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/**
 * Do not edit directly, this file was auto-generated.
 */</span>

<span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--color-primary</span><span class="token punctuation">:</span> #007bff<span class="token punctuation">;</span>
  <span class="token property">--color-secondary</span><span class="token punctuation">:</span> #6c757d<span class="token punctuation">;</span>
  <span class="token property">--spacing-none</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
  <span class="token property">--spacing-small</span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
  <span class="token property">--spacing-medium</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--typography-font-family-body</span><span class="token punctuation">:</span> Roboto<span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
  <span class="token property">--typography-font-size-base</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">--typography-font-size-lg</span><span class="token punctuation">:</span> 1.25rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="generating-sass-variables" tabindex="-1">Generating Sass Variables</h2>
<p>Now that we have this working, we can add another platform for Style Dictionary to generate code from. Let's get it to create Sass variables in a new <code>.scss</code> file. We need to add some more code to the <code>build.js</code> to get this to work.</p>
<pre class="language-js"><code class="language-js"><span class="token literal-property property">scss</span><span class="token operator">:</span> <span class="token punctuation">{</span>
 <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'scss'</span><span class="token punctuation">,</span>
 <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/'</span><span class="token punctuation">,</span>
 <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
   <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'_variables.scss'</span><span class="token punctuation">,</span>
   <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'scss/variables'</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
 <span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span></code></pre>
<p>So the full <code>build.js</code> code will look like this:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">import</span> StyleDictionary <span class="token keyword">from</span> <span class="token string">'style-dictionary'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> myStyleDictionary <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StyleDictionary</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">source</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src/tokens/**/*.json</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">platforms</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">css</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'css'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'variables.css'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'css/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">scss</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">transformGroup</span><span class="token operator">:</span> <span class="token string">'scss'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">buildPath</span><span class="token operator">:</span> <span class="token string">'build/'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">destination</span><span class="token operator">:</span> <span class="token string">'_variables.scss'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">format</span><span class="token operator">:</span> <span class="token string">'scss/variables'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">await</span> myStyleDictionary<span class="token punctuation">.</span><span class="token function">buildAllPlatforms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Running <code>npm run build</code> will now generate the <code>variables.css</code> file as well as a new <code>_variables.scss</code> file that will look like this:</p>
<pre class="language-scss"><code class="language-scss"><span class="token comment">// Do not edit directly, this file was auto-generated.</span>

<span class="token property"><span class="token variable">$color-primary</span></span><span class="token punctuation">:</span> #007bff<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$color-secondary</span></span><span class="token punctuation">:</span> #6c757d<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-none</span></span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-small</span></span><span class="token punctuation">:</span> 0.5rem<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$spacing-medium</span></span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$typography-font-family-body</span></span><span class="token punctuation">:</span> Roboto<span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$typography-font-size-base</span></span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$typography-font-size-lg</span></span><span class="token punctuation">:</span> 1.25rem<span class="token punctuation">;</span></code></pre>
<h2 id="where-we're-at%2C-and-where-can-we-go-to" tabindex="-1">Where we're at, and where can we go to</h2>
<p>We have explored the basics of setting up Style Dictionary to generate CSS custom properties and Sass variables from design tokens. Covering how design tokens help maintain consistency across platforms by acting as a shared source of truth for your design decisions.</p>
<p>In automating the conversion of tokens into platform-specific formats, Style Dictionary streamlines workflows, reduces errors, and ensures that design guidelines can be implemented accurately and efficiently.</p>
<p>Using a tool like Style Dictionary to automate the process of generating styles means you can be confident that your design tokens will always be up-to-date across all platforms. It can simplify the
collaboration between designers and developers by providing a unified, consistent source of truth for visual properties, leading to a more cohesive and polished final product.</p>
<p>Now that we’ve seen how to get started with Style Dictionary, there’s much more you can explore. In future articles, we’ll dive deeper into more advanced configurations.</p>
<p>I encourage you to check out the <a href="https://v4.styledictionary.com">Style Dictionary documentation</a> to learn about its extensive capabilities. You can also explore the example code on my <a href="https://github.com/sturobson/Style-Dictionary-Starter/tree/01-Getting-Started">GitHub repository</a> to see the end results and experiment with your own setups.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>What Else Can We Do With Design Tokens?</title>
      <link href="https://www.alwaystwisted.com/articles/what-else-can-we-do-with-design-tokens.html"/>
      <updated>2024-10-22T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/what-else-can-we-do-with-design-tokens.html</id>
      <content type="html">
        <![CDATA[
        <p>Design Tokens are a solution in Design System that allow teams to define and use their design decisions across disciplines, codebases, and frameworks.</p>
<p>Simply put they hold a name or ‘key’ for what the design decision is called and a ‘value’ which will get generated or exposed where needed.</p>
<p>Design Tokens are generally stored in a ‘single source of truth’ where they’re defined in one place and everyone else will use that or what is exported from it to use.</p>
<p>As a front-end developer I hvae often created and stored Design Tokens in code. This is generally in a text based file format called json, but it is (or perhaps was) possible to use the more white-space strict text format yaml.</p>
<h2 id="the-design-tokens-specification" tabindex="-1">The Design Tokens Specification</h2>
<p>Before talking about what else can we do with Design Tokens, let's look at what is expected as the bare minimum. This information is taken from the work that the <a href="https://www.w3.org/community/design-tokens/">Design Tokens Working Group</a> have been working on in <a href="https://tr.designtokens.org">creating a specifcation</a> for Design Tokens.</p>
<p>As mentioned, Design Tokens are typically defined in JSON format, and the files can be named with a <code>.tokens.json</code> or <code>.tokens</code> extension.</p>
<p>Design Tokens must include a <code>$name</code> and <code>$value</code>:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"tokenName"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#BADA55"</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Design Tokens must also include a <code>$type</code>. Applying a type allows tools to interpret the tokens <code>$value</code> accordingly. You can apply the <code>$type</code> per Design Token but you can also simplify this by applying ot at a group level.</p>
<p>Example showing <code>$type</code> being applied per token:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#BADA55"</span><span class="token punctuation">,</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#C0FFEE"</span><span class="token punctuation">,</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Example showing <code>$type</code> being applied per group:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"colors"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
    <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#BADA55"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"secondary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#C0FFEE"</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Design Tokens can hold more design decisions than colour so the standard defines various token types, including <code>color</code>, <code>dimension</code>, <code>fontWeight</code>, <code>duration</code>, <code>fontFamily</code>, <code>number</code> and <code>cubicBezier</code>.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"small"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">".25rem"</span><span class="token punctuation">,</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"dimension"</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"bold"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token number">700</span><span class="token punctuation">,</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontWeight"</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"slow"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"350ms"</span><span class="token punctuation">,</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"duration"</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"mono"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"Consolas"</span><span class="token punctuation">,</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"fontFamily"</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"line-height-normal"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token number">1.5</span><span class="token punctuation">,</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"number"</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"easing"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0.5</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"cubicBezier"</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Design Tokens can also, optionally, include a description that can help explain it's purpose:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"warning"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"$value"</span><span class="token operator">:</span> <span class="token string">"#FFF3CD"</span><span class="token punctuation">,</span>
    <span class="token property">"$type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
    <span class="token property">"$description"</span><span class="token operator">:</span> <span class="token string">"Use this colour for warning states"</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="can-we-do-more%3F" tabindex="-1">Can we do more?</h2>
<p>Way back in 2019 I first read about the idea of adding meta information to your design tokens <code>.json</code> objects from Christiano in their a qrticle – <a href="https://medium.com/bumble-tech/design-tokens-beyond-colors-typography-and-spacing-ad7c98f4f228">Design Tokens beyond colors, typography, and spacing</a> - the idea of meta information as part of a Design Token is also part of the proposed specification which states its use can help interoperability between tools and that we should restrict to information that is not necessarily vital to the understanding of the Design Token.</p>
<p>When I was helping Springer Nature revitalise their Design System efforts I took time to create and integrate Design Tokens into their existing code base.</p>
<p>As well as the <code>$key</code>, <code>$value</code>, and <code>$type</code> I also introduced meta information that assisted in the creating of documentation as well as specifying what syntax the tokens got generated to.</p>
<p>Below is an example of <code>json</code> that I worked on as part of the Design Tokens implementation in Springer Nature's Design System - Elements.</p>
<pre class="language-json"><code class="language-json"><span class="token property">"color"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
  <span class="token property">"primary"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"primary"</span><span class="token punctuation">,</span>
    <span class="token property">"value"</span><span class="token operator">:</span> <span class="token string">"{color.brand.500}"</span><span class="token punctuation">,</span>
    <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
    <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"The primary brand colour used for the website accents"</span><span class="token punctuation">,</span>
    <span class="token property">"category"</span><span class="token operator">:</span> <span class="token string">"color"</span><span class="token punctuation">,</span>
    <span class="token property">"meta"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token property">"public"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      <span class="token property">"deprecated"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
      <span class="token property">"documented"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      <span class="token property">"experimental"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
      <span class="token property">"SassVariable"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      <span class="token property">"themeable"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      <span class="token property">"CSSCustomProperty"</span><span class="token operator">:</span> <span class="token boolean">false</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Using this example, let's pick this apart to see what this meta information was for and how it was utilised.</p>
<h3 id="public" tabindex="-1">public</h3>
<p>This was used to show or hide certain Design Tokens, or groups of, from being displayed on the documentation site. Why -- because we were trying to have folks use the 'semantic' design decisions rather than the lower level 'raw' base layer design tokens</p>
<pre class="language-nunjucks"><code class="language-nunjucks"><span class="token delimiter punctuation">{%</span> <span class="token tag keyword">if</span> <span class="token variable">tokens</span><span class="token punctuation">.</span><span class="token variable">meta</span><span class="token punctuation">.</span><span class="token variable">public</span> <span class="token operator">%</span><span class="token punctuation">}</span>
  <span class="token operator">//</span> <span class="token variable">All</span> <span class="token variable">the</span> <span class="token variable">code</span> <span class="token keyword">for</span> <span class="token variable">documenting</span> <span class="token variable">the</span> <span class="token variable">token</span>
<span class="token punctuation">{</span><span class="token operator">%</span> <span class="token variable">endif</span> <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<h3 id="deprecated" tabindex="-1">deprecated</h3>
<p>Can be used to make your documentation site add a small 'banner' or note to the tokens documentation to state that teams should not use this going forward.</p>
<p>In nunjucks it could look something like this:</p>
<pre class="language-nunjucks"><code class="language-nunjucks"><span class="token delimiter punctuation">{%</span> <span class="token tag keyword">if</span> <span class="token variable">tokens</span><span class="token punctuation">.</span><span class="token variable">meta</span><span class="token punctuation">.</span><span class="token variable">deprecated</span> <span class="token operator">%</span><span class="token punctuation">}</span>
<span class="token operator">&lt;</span><span class="token variable">div</span> <span class="token variable">class</span><span class="token operator">=</span><span class="token string">"ds-docs-message ds-docs-message--deprecated"</span><span class="token operator">></span>
    <span class="token variable">This</span> <span class="token variable">token</span> <span class="token keyword">is</span> <span class="token test function">deprecated</span><span class="token punctuation">.</span> <span class="token variable">Please</span> <span class="token variable">update</span> <span class="token variable">to</span> <span class="token variable">the</span> <span class="token variable">latest</span> <span class="token variable">version</span><span class="token punctuation">.</span>
<span class="token operator">&lt;</span><span class="token operator">/</span><span class="token variable">div</span><span class="token operator">></span>
<span class="token punctuation">{</span><span class="token operator">%</span> <span class="token variable">endif</span> <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<p>We can also set replacements with it. We can also use this when generating pre-proccesor code like Sass to include a <code>@warn</code> rule to show folks it's being deprecated.</p>
<p>In Style Dictionary we can register a new format to show the deprecation as <code>@warn</code> rule.</p>
<pre class="language-js"><code class="language-js">StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'scss/deprecated-warnings'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">formatter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> dictionary<span class="token punctuation">.</span>allProperties
      <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span>
        token<span class="token punctuation">.</span>attributes<span class="token operator">?.</span>deprecated
          <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">@warn "</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>name<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token string">'.'</span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> is deprecated. Please update it.";</span><span class="token template-punctuation string">`</span></span>
          <span class="token operator">:</span> <span class="token string">''</span>
      <span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Which would output Sass to something like this</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@warn</span> <span class="token string">"color-primary is deprecated. Please update it."</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$color-primary</span></span><span class="token punctuation">:</span> #bada55<span class="token punctuation">;</span></code></pre>
<h3 id="experimental" tabindex="-1">experimental</h3>
<p>The initial work on moving Springer Natures Design System forward with a new version of Elements meant, at times, there would be tokens that may or may not be used in the end - this led to creating a boolean key/value pair to, again, create a 'banner' in the documentation.</p>
<p>Similar to the <code>deprecated</code> meta information - we can use something like Nunjucks to determine if the an additional message is needed if the token is experimental.</p>
<pre class="language-nunjucks"><code class="language-nunjucks"><span class="token delimiter punctuation">{%</span> <span class="token tag keyword">if</span> <span class="token variable">tokens</span><span class="token punctuation">.</span><span class="token variable">meta</span><span class="token punctuation">.</span><span class="token variable">experimental</span> <span class="token operator">%</span><span class="token punctuation">}</span>
<span class="token operator">&lt;</span><span class="token variable">div</span> <span class="token variable">class</span><span class="token operator">=</span><span class="token string">"ds-docs-message ds-docs-message--experimental"</span><span class="token operator">></span>
    <span class="token variable">This</span> <span class="token variable">token</span> <span class="token keyword">is</span> <span class="token test function">experimental</span><span class="token punctuation">.</span> <span class="token variable">Please</span> <span class="token variable">update</span> <span class="token variable">to</span> <span class="token variable">the</span> <span class="token variable">latest</span> <span class="token variable">version</span><span class="token punctuation">.</span>
<span class="token operator">&lt;</span><span class="token operator">/</span><span class="token variable">div</span><span class="token operator">></span>
<span class="token punctuation">{</span><span class="token operator">%</span> <span class="token variable">endif</span> <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<h3 id="sassvariable" tabindex="-1">SassVariable</h3>
<p>This was used to both generate the Sass variable so that it can be used and also display the Sass variable in the documentation.</p>
<h3 id="themeable" tabindex="-1">themeable</h3>
<p>When creating code from the design tokens - this would add <code>!default</code>. This would be as part of generating the code needed, in Style Dictionary we would have a registered format similar to this.</p>
<pre class="language-js"><code class="language-js">StyleDictionary<span class="token punctuation">.</span><span class="token function">registerFormat</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'scss/themeable-defaults'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">formatter</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> dictionary <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> dictionary<span class="token punctuation">.</span>allProperties
      <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> value <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">$</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>name<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token string">'.'</span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>token<span class="token punctuation">.</span>value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> token<span class="token punctuation">.</span>attributes<span class="token operator">?.</span>themeable <span class="token operator">?</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> !default;</span><span class="token template-punctuation string">`</span></span> <span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This would generate something like this.</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$color-primary</span></span><span class="token punctuation">:</span> #bada55 <span class="token statement keyword">!default</span><span class="token punctuation">;</span></code></pre>
<h3 id="csscustomproperty" tabindex="-1">CSSCustomProperty</h3>
<p>Similarly, this was used to generate the associated CSS custom property and also display it in the documentation</p>
<h2 id="wrapping-up" tabindex="-1">Wrapping Up</h2>
<p>Design Tokens are an essential part of Design Systems, by providing a way to develop a shared language it helps to close &quot;the gap&quot; between design and development.</p>
<p>As I have found in my consultancy work, adding layers of meta information can help with documenting, maintaining, and evolving the Design Tokens of a Design System over time.</p>
<p>Ultimately, Design Tokens can be more than storing values. They can be a way to create a cohesive, adaptable, future-proof design framework that grows with your project.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Creating Design System-Friendly Snowflakes with Utility Classes</title>
      <link href="https://www.alwaystwisted.com/articles/creating-design-system-friendly-snowflakes-with-utility-classes.html"/>
      <updated>2024-10-21T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/creating-design-system-friendly-snowflakes-with-utility-classes.html</id>
      <content type="html">
        <![CDATA[
        <img alt="a combined image of a screenshot of Sketch, a closer screenshot of the component, and a screenshot of some code"  src="/images/articles/snowflakes-and-tokens.jpg"/>
<p>Whilst I was helping <a href="https://www.embl.org">EMBL</a> in creating a new Design System based on a brand refresh and website re-organisation (going from 7 individual websites to one) we got to a point where other teams started to require unique components or patterns that would not necessarily fit into the larger Design System (The Visual Framework) but still needed to be ‘of the Design System’.</p>
<p>Teams needed either completely new components or they wanted to enhance or change certain characteristics of existing components to fit their unique needs.</p>
<p>I came up with a pragmatic approach that would help teams make these components whilst not venturing far away from the overall design language of the Design System.</p>
<p>In generating CSS Utility Classes from the Design Tokens it gave teams that needed to sway from the Design System the ability to create unique components (snowflakes) that were of the Design System.</p>
<h2 id="snowflakes-in-design-systems" tabindex="-1">Snowflakes in Design Systems</h2>
<p>A ’snowflake’ in a Design System is a one-off component that could be needed for a specific project, but there is an understanding that it may not be reused or may only be required by one team within an organisation.</p>
<p>These components could be problematic as part of a Design System as their intention is normally restricted to a specific use case for a certain team or brand.</p>
<p>They could potentially disrupt the overall Design System by creating the perception that it should include every component, even if a component is only intended for a specific part of a single page (or more). Instead, the Design System should primarily house components that are widely used, thoroughly tested, and essential across multiple areas.</p>
<p>To help teams still have some freedom in creating new components that they might need but it being something that may never end up in the Design System creating a solution like Design Token specific utility classes they can create these components with a level of confidence that it would match with the surrounding components from the Design System on the page.</p>
<p>When addressing the need for a team to create a unique, special, one-off snowflake I found that supplying utility classes based on the base layer and semantic layer of the Design Tokens allows them to create what they need without diverging from the look and feel of the Design System.</p>
<h2 id="utility-classes-from-design-tokens" tabindex="-1">Utility Classes from Design Tokens</h2>
<p>Utility classes can be seen as small, single-purpose CSS classes that apply specific styles directly to elements. Each utility class typically represents a single style rule or a small set of related styles, such as setting margin, padding, colour, font size, or alignment. For example:</p>
<ul>
<li><code>.u-background-color--primary</code> might apply <code>background-color: green;</code></li>
<li><code>.u-card-spacing--xl</code> could set padding to <code>2rem</code></li>
<li><code>.u-typography--button</code> might set the font family to a specific typeface for buttons</li>
</ul>
<p>Utility classes can play a vital role in enhancing flexibility within a Design System by providing a simple, consistent way to apply styles directly in the HTML. This approach can help teams adapt and create custom components (snowflakes) without the need to write new CSS each time they encounter a unique design requirement.</p>
<p>By generating these utility classes from Design Tokens, teams can be confident that any custom components they create will still align with the overall visual language of the Design System.</p>
<p>Utility classes derived directly from the Design Tokens ensure that any changes made to the tokens will automatically propagate throughout the project. This means that if a token value is updated, such as adjusting a colour or changing a spacing scale, the utility classes will reflect these changes everywhere they are used, maintaining consistency across the system.</p>
<h2 id="creating-a-snowflake-component" tabindex="-1">Creating a Snowflake Component</h2>
<p>Although the Design System that I created with EMBL had several well thought out components that were readily available their came a point where one team needed something similar to the card component. From their user tested designs they needed some extra elements as well as some different spacing and sizing because of position of this card on the page.</p>
<p>At first they wanted a whole new component that would be part of the Design System but after some back-and-forth discussions it was agreed that they would take the existing card component and adapt it using utility classes. Again, this way they can be confident that their unique 'snowflake' component will match with the rest of the page.</p>
<p>I had some time on my hands that afternoon, so I decided to see how easily it would be to augment the existing component and what utility classes would be needed to match the design.</p>
<img alt="a screenshot of the Sketch Application showing a book page with a unique sidebar design" src="/images/articles/snowflakes-sketch.jpg"/>
<p>The Sketch file in the image above was what we were working towards. There are a few components that were part of the system that we could use, the <code>figure</code> component for the book cover image, the <code>button</code> for the, um, button. There was a couple of list items and the horizontal rule but there was also some typography and spacing treatment that was specific to this 'snowflake'.</p>
<p>The image below shows this snowflake component next to the HTML that was written and adapted for it. There are additional CSS classes with <code>vf-u-</code> that denoted they were a utility class within the HTML.</p>
<img alt="a screenshot of the unique sidebar design with the related HTML next to it" src="/images/articles/snowflakes-code.jpg"/>
<p>Using utility classes along side or within existing components allowed the team to have their unique 'snowflake' component but making sure that the changes and additions applied still matched the overall Design System.</p>
<h2 id="balancing-consistency-and-flexibility" tabindex="-1">Balancing Consistency and Flexibility</h2>
<p>Utility classes can provide a flexible and efficient solution for teams who need to create unique, project-specific components without straying from the core design language. By leveraging utility classes, we can avoid the pitfalls of adding variations and unique components as a permanent part of the Design System. Instead, teams could customise existing components to suit their needs, confident that their changes would still harmonise with the Design System.</p>
<p>This approach also means that any updates to the underlying Design Tokens could be automatically reflected in these custom components.</p>
<p>It can allow for greater adaptability across different projects ensuring that even when teams needed to step outside the core Design System, they were still operating ‘of the system.’</p>
<p>Ultimately, generating utility classes from Design Tokens provided the balance between consistency and flexibility, helping EMBL create a cohesive, scalable, and user-friendly Design System.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>CSS Logical Properties, easier with Sass</title>
      <link href="https://www.alwaystwisted.com/articles/css-logical-properties-and-sass.html"/>
      <updated>2024-10-11T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/css-logical-properties-and-sass.html</id>
      <content type="html">
        <![CDATA[
        <p>Using logical properties when writing CSS allows your code to adapt more naturally to various text directions and writing modes, such as left-to-right (LTR), right-to-left (RTL), or even vertical text.</p>
<p>Unlike traditional properties like <code>margin-left</code> or <code>padding-top</code>, logical properties help future-proof your designs by removing assumptions about content flow and the needs of your site visitors.</p>
<p>Rather than thinking in fixed directions, logical properties enable your designs to adapt automatically. This improves both consistency and flexibility, making your CSS more scalable and versatile for the different contexts it may encounter.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p><a href="https://front-end.social/@shadeed9">Ahmad</a> has <a href="https://ishadeed.com/article/css-logical-properties/">a fantastic deep dive into CSS logical properties</a>.</p>
</div>
<h2 id="the-problem-with-logical-properties" tabindex="-1">The problem with logical properties</h2>
<p>They can be long, really long.</p>
<p>Whilst logical properties are a fantastic way forward offering flexibility and adaptability, they can introduce a level of verbosity that can make your code appear more cumbersome. Instead of using <code>margin-left</code>, you would need to write <code>margin-inline-start</code>, which can feel longer and less intuitive.</p>
<p>Going all in on using logical properties and as more are used, such as <code>border-block-end-width</code>, <code>border-inline-start-color</code>, the increased verbosity can make your stylesheets harder to read and potentially harder to maintain.</p>
<h2 id="let%E2%80%99s-make-things-easier-with-sass" tabindex="-1">Let’s make things easier with Sass</h2>
<p>One approach to handle the potential verbosity and cognitive load of using logical properties is to make use of the (still) widely used preprocessor, Sass. Using logical properties can feel to repetitive and could require extra thought as you translate the more traditional properties into their newer logical counterparts.</p>
<p>By using Sass with its functions, maps, variables, and mixins, you can simplify the syntax, reduce any possible mental overhead, and allow for more readable, reusable, and intuitive code that will automatically handle the complexity of logical property mapping.</p>
<h2 id="the-sass-we-need" tabindex="-1">The Sass we need</h2>
<p>When thinking about how I could use the features of Sass to make it easier to write CSS logical properties I thought about what properties to work with and what CSS values to be able to apply.</p>
<p>Although CSS logical properties go way beyond these examples, I thought It would be good to limit the amount of options to the CSS I write day-to-day that could benefit from these mixins. This boiled down to <code>margin</code>, <code>padding</code>, <code>border</code> and it’s derivatives including <code>border-radius</code> as it’s slightly different as it’s more ‘corners’ thant ‘sides.</p>
<p>I also thought that we should be able to allow the author to write in several ways which are: a raw CSS value, a Sass <code>$variable</code> (we’re using Sass after all) or a CSS custom property.
Deciding on this as ‘the brief’ I started to work on writing the code.</p>
<h3 id="a-function-for-values" tabindex="-1">A function for values</h3>
<p>In a Sass mixin, passing through a raw CSS value or Sass <code>$variable</code> is relatively straightforward but when it comes to using CSS custom properties in Sass you will eventually have to deal with interpolation. I wanted the value an author prescribes to be as less taxing as possible. I wanted an author ot be able to write</p>
<ul>
<li><code>40px</code></li>
<li><code>$padding-size-l</code></li>
<li><code>--margin-size--0</code></li>
</ul>
<p>To avoid having to write the interpolation and for the author not to have to write <code>var()</code> each time I created a small little Sass function that checks the start of the <code>$value</code>, if it contains <code>--</code> then it will return the <code>$value</code> as a CSS custom property wrapped in <code>var()</code>. If the value doesn’t contain <code>--</code> at the start it simply returns the value.</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@function</span> <span class="token function">slp-process-value</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">@if</span> <span class="token function">type-of</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token string">'string'</span> <span class="token operator">and</span> <span class="token function">str-index</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">,</span> <span class="token string">'--'</span><span class="token punctuation">)</span> <span class="token selector">==1 </span><span class="token punctuation">{</span>
    <span class="token keyword">@return</span> <span class="token function">var</span><span class="token punctuation">(</span><span class="token variable">#{$value}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">@else</span> <span class="token punctuation">{</span>
    <span class="token keyword">@return</span> <span class="token variable">$value</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="creating-maps-for-cleaner-mixins" tabindex="-1">Creating maps for cleaner mixins</h3>
<p>My first efforts in creating a Sass mixin had me using the <code>@if</code> and <code>@else</code> Sass control directives.</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@mixin</span> <span class="token function">logical-margin</span><span class="token punctuation">(</span><span class="token variable">$side</span><span class="token punctuation">,</span> <span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">@if</span> <span class="token selector"><span class="token variable">$side</span> == top </span><span class="token punctuation">{</span>
    <span class="token property">margin-block-start</span><span class="token punctuation">:</span> <span class="token variable">$value</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">@else if</span> <span class="token selector"><span class="token variable">$side</span> == bottom </span><span class="token punctuation">{</span>
    <span class="token property">margin-block-end</span><span class="token punctuation">:</span> <span class="token variable">$value</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">@else if</span> <span class="token selector"><span class="token variable">$side</span> == left </span><span class="token punctuation">{</span>
    <span class="token property">margin-inline-start</span><span class="token punctuation">:</span> <span class="token variable">$value</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">@else if</span> <span class="token selector"><span class="token variable">$side</span> == right </span><span class="token punctuation">{</span>
    <span class="token property">margin-inline-end</span><span class="token punctuation">:</span> <span class="token variable">$value</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>An author could then write:</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@include</span> <span class="token function">logical-margin</span><span class="token punctuation">(</span>top<span class="token punctuation">,</span> 30px<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>which would output in a stylesheet as:</p>
<pre class="language-css"><code class="language-css"><span class="token property">margin-block-start</span><span class="token punctuation">:</span> 30px<span class="token punctuation">;</span></code></pre>
<p>Although the person authoring may never need to touch or see these mixins I think it would be cleaner, and less repetitive when writing more mixins to make use of Sass maps. We want to be able to not just port the complexity of the <code>@if</code> / <code>@else</code> statement to the Sass map but to simplify the possibilities so we can reuse the map as much as possible.</p>
<p>As we will be wanting to use these logical property Sass mixins for <code>padding</code>, <code>margin</code>, and <code>border</code> we can create a Sass map and mixins to not need those words.
Instead tying the Sass map to margin, for example:</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$logical-margin-map</span></span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
  <span class="token property">top</span><span class="token punctuation">:</span> margin-block-start<span class="token punctuation">,</span>
  <span class="token property">bottom</span><span class="token punctuation">:</span> margin-block-end<span class="token punctuation">,</span>
  <span class="token property">left</span><span class="token punctuation">:</span> margin-inline-start<span class="token punctuation">,</span>
  <span class="token property">right</span><span class="token punctuation">:</span> margin-inline-end<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>We can simplify it and let the Sass mixin do some work:</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$logical-map</span></span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
  <span class="token property">top</span><span class="token punctuation">:</span> block-start<span class="token punctuation">,</span>
  <span class="token property">bottom</span><span class="token punctuation">:</span> block-end<span class="token punctuation">,</span>
  <span class="token property">left</span><span class="token punctuation">:</span> inline-start<span class="token punctuation">,</span>
  <span class="token property">right</span><span class="token punctuation">:</span> inline-end<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>With the above Sass map we can reuse it in our mixins for <code>border</code>, <code>margin</code>, and <code>padding</code>.</p>
<h3 id="making-the-mixin" tabindex="-1">Making the mixin</h3>
<p>So, we have our Sass function that works out if the <code>$value</code> passed is a CSS custom property or not and we have a Sass map that helps the simplifying and tying together of traditional CSS properties and the newer logical properties. We need a mixin to put it all together.</p>
<p>So for the following examples I will concentrate on just on of the possible mixins. A Sass mixin for easier logical properties for with margin.</p>
<p>We want our Sass mixin to take two variables: the <code>$side</code> that we want the rule to change and the <code>$value</code> of how much to apply. To determine if the Sass mixin is dealing with a raw CSS value, a Sass <code>$variable</code> or a CSS custom property we want the <code>$value</code> to go through our function we have created. To determine which <code>$side</code> we want to effect and have the correct logical property printed out in CSS we need fetch that correct value from the map. Then, if the <code>$side</code> value is correct (top,bottom,left,right) we want to generate the CSS.</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@mixin</span> <span class="token function">logical-margin</span><span class="token punctuation">(</span><span class="token variable">$side</span><span class="token punctuation">,</span> <span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token property"><span class="token variable">$processed-value</span></span><span class="token punctuation">:</span> <span class="token function">slp-process-value</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property"><span class="token variable">$logical-side</span></span><span class="token punctuation">:</span> <span class="token function">map-get</span><span class="token punctuation">(</span><span class="token variable">$logical-map</span><span class="token punctuation">,</span> <span class="token variable">$side</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">@if</span> <span class="token selector"><span class="token variable">$logical-side</span> </span><span class="token punctuation">{</span>
    #<span class="token punctuation">{</span><span class="token string">'margin-'</span> <span class="token operator">+</span> <span class="token variable">$logical-side</span><span class="token punctuation">}</span><span class="token punctuation">:</span> <span class="token variable">#{$processed-value}</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">@else</span> <span class="token punctuation">{</span>
    <span class="token keyword">@warn</span> <span class="token string">"Invalid side `#{$side}` specified for logical-margin mixin."</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>We would then write out similar mixins for the padding and border rules.</p>
<h3 id="using-the-mixin" tabindex="-1">Using the mixin</h3>
<p>Now we have the Sass function, map, and mixin we can then use it in our codebase:</p>
<pre><code>:root {
  --padding-l: 2rem;
}

$margin: 4rem;

body {
 @include logical-border-width(top, 1rem);
 @include logical-border-color(top, #BADA55);
 @include logical-border-style(top, solid);

 @include logical-margin(top, $margin);

 @include logical-padding(left, --padding);
 @include logical-padding(right, --padding);
}
</code></pre>
<p>Which would generate this CSS:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span>
  <span class="token property">--padding-l</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">body</span> <span class="token punctuation">{</span>
  <span class="token property">border-block-start-width</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span>
  <span class="token property">border-block-start-color</span><span class="token punctuation">:</span> #bada55<span class="token punctuation">;</span>
  <span class="token property">border-block-start-style</span><span class="token punctuation">:</span> solid<span class="token punctuation">;</span>

  <span class="token property">margin-block-start</span><span class="token punctuation">:</span> 4rem<span class="token punctuation">;</span>

  <span class="token property">padding-inline-start</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--padding<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">padding-inline-end</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--padding<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="border-radius-hits-different" tabindex="-1">border-radius hits different</h2>
<p>As I previously mentioned unlike CSS properties for rules like margin and padding that affect the sides of an element on the page <code>border-radius</code> logical properties effect the corners and because of this the syntax may seem a little odd. Rather than <code>border-top-left-radius</code> with logical properties you can write <code>border-start-start-radius</code>.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p><a href="https://front-end.social/@michelle">Michelle Barker</a> has <a href="https://css-irl.info/logical-border-radius/">a great article about logical properties and <code>border-radius</code></a> that is well worth reading.</p>
</div>
<p>To make use of Sass to simplify writing CSS for <code>border-radius</code> using logical properties we can still use the Sass function above, but we will need a new Sass map to accommodate the different syntax and another mixin to generate the final code.</p>
<p>For the Sass map we can write something similar to the <code>$logical-map</code> map we created earlier.</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$logical-border-radius-map</span></span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
  <span class="token property">top-left</span><span class="token punctuation">:</span> start-start<span class="token punctuation">,</span>
  <span class="token property">top-right</span><span class="token punctuation">:</span> start-end<span class="token punctuation">,</span>
  <span class="token property">bottom-left</span><span class="token punctuation">:</span> end-start<span class="token punctuation">,</span>
  <span class="token property">bottom-right</span><span class="token punctuation">:</span> end-end<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>As the CSS for the <code>border-radius</code> is written differently to something like <code>margin</code> or <code>padding</code> we would need a new Sass mixin that accommodates this, putting the logical property between <code>border-</code> and <code>radius</code>. This is a relatively simple re-jig of the Sass mixin we have already created.</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@mixin</span> <span class="token function">logical-border-radius</span><span class="token punctuation">(</span><span class="token variable">$corner</span><span class="token punctuation">,</span> <span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token property"><span class="token variable">$processed-value</span></span><span class="token punctuation">:</span> <span class="token function">slp-process-value</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property"><span class="token variable">$logical-corner</span></span><span class="token punctuation">:</span> <span class="token function">map-get</span><span class="token punctuation">(</span><span class="token variable">$logical-border-radius-map</span><span class="token punctuation">,</span> <span class="token variable">$corner</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">@if</span> <span class="token selector"><span class="token variable">$logical-corner</span> </span><span class="token punctuation">{</span>
    #<span class="token punctuation">{</span><span class="token string">'border-'</span> <span class="token operator">+</span> <span class="token variable">$logical-corner</span> <span class="token operator">+</span> <span class="token string">'-radius'</span><span class="token punctuation">}</span><span class="token punctuation">:</span> <span class="token variable">#{$processed-value}</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">@else</span> <span class="token punctuation">{</span>
    <span class="token keyword">@warn</span> <span class="token string">"Invalid corner `#{$corner}` specified for logical-border-radius mixin."</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<hr>
<p>Wrapping up, I hope this post highlights how Sass can be a powerful tool for managing CSS logical properties in your everyday workflow. By leveraging Sass to handle the potential verbosity and complexity of logical properties, you can keep your codebase clean and easier to maintain, even as your designs scale and evolve. This approach simplifies the process, ensuring your CSS remains adaptable and efficient, without getting bogged down by repetitive or lengthy syntax.</p>
<p>You can start using the <a href="https://www.npmjs.com/package/sass-logical-properties">Sass Logical Properties package</a> right away, or if you’re curious about how it works, head over to the <a href="https://github.com/sturobson/sass-logical-properties">GitHub repo</a> to view the source code. With these tools, you’ll find working with logical properties far more manageable in your next project.</p>
<div class="at-c-note"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -10 110 135"><path d="M72.812 78a3.124 3.124 0 0 0-3.125 3.125v4.938a3.127 3.127 0 0 1-3.125 3.124H12.5a3.13 3.13 0 0 1-3.125-3.124V13.936a3.13 3.13 0 0 1 3.125-3.124h54.062a3.127 3.127 0 0 1 3.125 3.124v14.22a3.124 3.124 0 1 0 6.25 0v-14.22c0-5.167-4.207-9.374-9.375-9.374H12.5c-5.168 0-9.375 4.207-9.375 9.375v72.124c0 5.169 4.207 9.376 9.375 9.376h54.062c5.168 0 9.375-4.208 9.375-9.376v-4.937A3.124 3.124 0 0 0 72.812 78z"/><path d="M56.523 21.309H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.124 3.124 0 1 0 0-6.25zM22.531 78.688h18.75a3.124 3.124 0 1 0 0-6.25h-18.75a3.124 3.124 0 1 0 0 6.25zM59.648 38.871a3.124 3.124 0 0 0-3.125-3.125H22.546a3.124 3.124 0 1 0 0 6.25h33.977a3.122 3.122 0 0 0 3.125-3.125zM22.547 56.438h16.988a3.124 3.124 0 1 0 0-6.25H22.547a3.124 3.124 0 1 0 0 6.25zM93.68 33.773c-4.254-4.258-11.18-4.258-15.434 0l-26.32 26.312a5.905 5.905 0 0 0-1.637 3.184l-1.441 8.53a5.916 5.916 0 0 0 1.648 5.157 5.915 5.915 0 0 0 5.157 1.645l8.527-1.442a5.9 5.9 0 0 0 3.191-1.644L93.676 49.21c4.258-4.254 4.258-11.18.004-15.438zm-30.543 37.23-8.05 1.36 1.26-7.864 18.747-18.742 6.613 6.613zm26.121-26.211-3.137 3.148-6.601-6.605 3.144-3.145a4.656 4.656 0 0 1 3.301-1.367c1.195 0 2.39.457 3.3 1.367a4.68 4.68 0 0 1-.007 6.602z"/></svg><p>I realise that while Sass simplifies logical properties, adding a build step isn’t always the easiest solution for everyone. However, for those already using Sass, it can help reduce complexity, improve maintainability, and enhance readability.</p>
</div>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>My Favourite Design Systems</title>
      <link href="https://www.alwaystwisted.com/articles/my-favourite-design-systems.html"/>
      <updated>2024-10-10T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/my-favourite-design-systems.html</id>
      <content type="html">
        <![CDATA[
        <p>Whether they are useful for anyone else but teams using them, or ‘masquerading’ as a marketing tool I really enjoy poring over the details of publicly available Design Systems documentation sites. Running the <a href="https://news.design.systems">Design Systems Newsletter</a> I include ones where I’ve found something new and interesting but there are always ones I go back to. I thought it would be nice to share a quick post with my all time favourites. So, in no particular order, here goes.</p>
<h2 id="nordhealth" tabindex="-1"><a href="https://nordhealth.design">Nordhealth</a></h2>
<p>Watching <a href="https://arie.ls">Arielle</a>’s work on Design Systems from <a href="https://vueds.com">VueDS</a> to <a href="https://www.duetds.com">Duets Design System</a> and now at Nordhealth. I’ve always enjoyed the attention to detail in the documentation sites. The added little features like opening up a component in CodePen. Always lovely to revisit and see what’s been updated and improved.</p>
<a class="at-c-link_with-image" href="<https://nordhealth.design>">
<img alt="Nord Design System Website" src="/images/articles/nord-design-system.png">
</a><h2 id="github-primer" tabindex="-1"><a href="https://primer.style">Github Primer</a></h2>
<p>I’ve been a fan of Primer since it was predominately only a CSS framework. It’s been interesting to watch it grow, become a monorepo, stop being a monorepo, and the incremental touches get added. It’s certainly helped me develop my opinions on Design Systems over the last ~10 years.</p>
<a class="at-c-link_with-image" href="<https://primer.style>">
<img alt="Github Primer Website" src="/images/articles/github-primer.png">
</a><h2 id="adobe-spectrum" tabindex="-1"><a href="https://spectrum.adobe.com">Adobe Spectrum</a></h2>
<p>Seeing <a href="https://www.youtube.com/watch?v=BltrdvKsrsM">a talk about Design Systems At Scale within Adobe Spectrum</a> the day they released Spectrum CSS I was instantly digging into the details. Holy-moly that was a lot of CSS custom properties.</p>
<a class="at-c-link_with-image" href="<https://spectrum.adobe.com>">
<img alt="Adobe Spectrum Website" src="/images/articles/adobe-spectrum.png">
</a><h2 id="atlassian-design-system" tabindex="-1"><a href="https://atlassian.design">Atlassian Design System</a></h2>
<p>Similarly to Github’s Primer, it’s been interesting to watch Atlassian evolve over time. If memory serves correct there was a period where design and development were separate websites. Now all under one domain there’s a lot of detail and interesting ways of documenting things to relish at here.</p>
<a class="at-c-link_with-image" href="<https://atlassian.design>">
<img alt="Atlassian Design System Website" src="/images/articles/atlassian-design-system.png">
</a><h2 id="ibm-carbon-design-system" tabindex="-1"><a href="https://carbondesignsystem.com">IBM Carbon Design System</a></h2>
<p>Again, Carbon has seen a similar evolution to others on this list. The amount of information per component is enormous with some great ideas on displaying how they can, should, and should not be used.</p>
<a class="at-c-link_with-image" href="<https://carbondesignsystem.com>">
<img alt="IBM Carbon Website" src="/images/articles/carbon-design-system.png">
</a><h2 id="shopify-polaris" tabindex="-1"><a href="https://polaris.shopify.com">Shopify Polaris</a></h2>
<p>Polaris was a documentation site I kept coming back to time and again when working on the Design Tokens I worked on whilst contracting at Monotype. And, again - another documentation that has evolved dramatically over time. Their Design Tokens documentation started as simply <a href="https://github.com/salesforce-ux/theo">Theo</a>’s HTML output to something grander, and more informative.</p>
<a class="at-c-link_with-image" href="<https://polaris.shopify.com>">
<img alt="Shopify Polaris Website" src="/images/articles/shopify-polaris.png">
</a><h2 id="other-sites" tabindex="-1">Other Sites</h2>
<p>The above are my favourites, but there are many, many more. Luckily you don’t have to continuously search the internet for them as some lovely folk in the community have created online libraries of existing Design Systems:</p>
<a class="at-c-link_with-image" href="<https://component.gallery>">
<img alt="Component Gallery Website" src="/images/articles/the-component-gallery.png">
</a><a class="at-c-link_with-image" href="<https://designsystemsrepo.com/design-systems>">
<img alt="Design Systems Repo List Website" src="/images/articles/design-systems-surf-database.png">
</a><a class="at-c-link_with-image" href="<https://designsystems.surf>">
<img alt="Design Systems Surf Database Website" src="/images/articles/design-systems-repo-list.png">
</a>
      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Tokens, Components, and 24Ways</title>
      <link href="https://www.alwaystwisted.com/articles/design-tokens-components-and-24ways.html"/>
      <updated>2019-12-14T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-tokens-components-and-24ways.html</id>
      <content type="html">
        <![CDATA[
        <p>Once again, Christmas is nearly upon us and that means it’s the time of year where there’s a fantastic new article on <a href="https://24ways.org/2019/">published on 24ways every day</a> on the lead up to Christmas Day.</p>
<p>Two years ago I was excited to write my first article for <a href="https://www.twitter.com/drewm">Drew</a> and the team where I wrote about my experimentation with <a href="https://24ways.org/2017/design-systems-and-css-grid/">CSS Grid within Design Systems</a> in my client work at the time.</p>
<p>Two years later and I’m still working with helping organisations and their Design Systems and this last year I have managed to get back into <a href="https://noti.st/sturobson">public speaking</a> after a self-imposed hiatus. The last couple of talks have been about <a href="https://www.google.com/search?client=safari&amp;rls=en&amp;q=design+tokens&amp;ie=UTF-8&amp;oe=UTF-8">Design Tokens</a> and how we can use them when creating reusable components for our Design System.</p>
<p>I felt that parts of the talk would make for a great overview of what Design tokens are, why we should look to use them, how and where we can start implementing them, and how they can help make component design more maintainable, consistent, and scaleable and empower every member of the team to make use of them.</p>
<p>I hope to expand on most of the points I have made in the article in a larger wish to try and share more in 2020.</p>
<p><a href="https://24ways.org/2019/design-tokens-and-component-based-design/">Design Tokens and Component Based Design</a></p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Systems London 2019 - Sue Andor</title>
      <link href="https://www.alwaystwisted.com/articles/design-systems-london-2019-sue-andor.html"/>
      <updated>2019-11-15T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-systems-london-2019-sue-andor.html</id>
      <content type="html">
        <![CDATA[
        <ul>
<li>What is an expert user
<ul>
<li>part and parcel of an organisation’s operation - staff / partner / middleman</li>
<li>Have subject matter expertise</li>
<li>Use a digital interface</li>
<li>An expert user = seen as internal staff</li>
</ul>
</li>
<li>We’ve come a long way with Design Systems but not for internal staff.</li>
<li>Can’t we just use our existing Design System?
<ul>
<li>A sensible choice perhaps.</li>
<li>Saves some money.</li>
<li>But does it work?</li>
<li>Is the context design agnostic?</li>
</ul>
</li>
<li>A food delivery service has different contexts that the user and the rider need so the design should be different</li>
<li>A judge does not ‘tick boxes’ so the GDS one form element for one page does not work for the judicial service</li>
<li>How do you create a design system while developing a product
<ul>
<li>inputs are as important as outputs..</li>
<li>include research in your design system.</li>
<li>Link research to user stories within your early design system.</li>
<li>Include UX - information architecture.</li>
<li>Include UI components and elements.</li>
<li>A single source of truth for design decisions.</li>
</ul>
</li>
<li>Design for internal users improves ROI.</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Systems London 2019 - Siddharth Kshetrapal</title>
      <link href="https://www.alwaystwisted.com/articles/design-systems-london-2019-siddharth-kshetrapal.html"/>
      <updated>2019-11-15T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-systems-london-2019-siddharth-kshetrapal.html</id>
      <content type="html">
        <![CDATA[
        <ul>
<li>it feels like everyone is shouting design systems and won’t stop</li>
<li>what is a design system?
<ul>
<li>way - principles and patterns.</li>
<li>how - shared and integrated.</li>
<li>why - define the overall design of a product.</li>
</ul>
</li>
<li>Design systems mean different things for different companies. It depends on the company size, culture - so yes - Bootstrap is a design system.</li>
<li>Working on the design of components allowed them to look at all the requirements of the component. The states, the tab order, the error messages. Which gave the developers all of the things they needed to implement it.</li>
<li>All products are not created equal. Building the design system for the application wasn’t made for marketing in mind. Bigger fonts, larger spacing. Design Tokens allowed to use the same components across teams more.</li>
<li>But they wanted teams to be able to ‘tweak’ the components without relying on design tokens and rebuilding the components.</li>
<li>Clean code doesn’t happen by accident.</li>
<li>Not having the time or the size of company to work on a design system, you can work on parts of it as and when. Creating a ‘system’ that helps you design a design system.</li>
<li>Like a Swiss Army knife of tools but you can’t have it all at once, so you start with a smaller, simpler knife and build up.</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Systems London 2019 - Shaun Bent</title>
      <link href="https://www.alwaystwisted.com/articles/design-systems-london-2019-shaun-bent.html"/>
      <updated>2019-11-15T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-systems-london-2019-shaun-bent.html</id>
      <content type="html">
        <![CDATA[
        <ul>
<li>
<p>2006 - No designers, they made mock-ups in MS Paint.</p>
</li>
<li>
<p>2008 - Spotify released on the desktop</p>
</li>
<li>
<p>The different platforms Spotify was on were owned by different teams for those platforms</p>
</li>
<li>
<p>In 2013 Spotify decided to align all things to a single brand to address the fragmentation. It was when it started to look like the dark themed application we see today.</p>
</li>
<li>
<p>After the Design System for the new consistency was created the team creating it was disbanded.</p>
</li>
<li>
<p>In 2015 Spotify tweaked the design, including their green. With the previous team disbanded they needed to start again with GLUE. The Spotify Design System.</p>
</li>
<li>
<p>Two challenges with GLUE.</p>
<ul>
<li>Autonomy, with ‘The Spotify Model’. Having a single team created a bottleneck. One team owned the UI - teams broke away, creating their own components</li>
<li>Spotify is everywhere, Spotify changed direction to being more than just an application. Which leads to 45 individual experiences.</li>
<li>The GLUE. approach was never going to scale across 45 platforms.</li>
<li>The GLUE. had become unstuck - the decision was to close down the team. The team was disbanded but the Design System had continued usage.</li>
</ul>
</li>
<li>
<p>A team was created to solve these new problems. Creating the DLS (Design Language System).</p>
<ul>
<li>Design Tokens to the rescue! Allowed the language to go to the 45 platforms. Allowed them to make small changes that would get applied to all projects.</li>
<li>Client facing applications started to have its own Design System being created - Tape. It had massive, grassroots adoptions. Tape was open, GLUE. was closed.</li>
</ul>
</li>
<li>
<p>As it was open - Tape has become the de facto Design System for Spotify.</p>
</li>
<li>
<p>Now Spotify has 3 official design systems. But, through research they found 22 (and counting) independent Design Systems being used across Spotify.</p>
</li>
<li>
<p>Having tried Centralised and De-Centralised systems they need to find the right balance between these two options.</p>
<ul>
<li>45_+ platforms</li>
<li>22 design systems</li>
<li>~200 designers</li>
<li>~2000 developers</li>
<li>1 Spotify</li>
</ul>
</li>
<li>
<p>“Design Systems are for people” — Jina</p>
</li>
<li>
<p>Now they are creating Encore</p>
<ul>
<li>Creating a Foundation with Design Tokens</li>
<li>Web - a common base for all of Spotify’s web experiences</li>
<li>Mobile</li>
<li>Local Design Systems - tailored for specific use cases</li>
<li>Encore for X - extensible architecture. Embraces the autonomous culture.</li>
<li>Local Design Systems are built on top - but they doesn’t need to be 22 of them.</li>
<li>Each system needs to provide design, documentation and code.</li>
<li>Encore has different squads across the world. Working together.</li>
</ul>
</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Systems London 2019 - Miranda Garrido</title>
      <link href="https://www.alwaystwisted.com/articles/design-systems-london-2019-miranda-garrido.html"/>
      <updated>2019-11-15T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-systems-london-2019-miranda-garrido.html</id>
      <content type="html">
        <![CDATA[
        <ul>
<li>They’ve worked with a lot of start-ups, accelerators and small companies.</li>
<li>Getting invested early means they can help in many different ways.</li>
<li>Design Systems at startups - you can over commit or they can be ignored.</li>
<li>Taking too much time in creating one rather than achieving other business goals.</li>
<li>They were asked to stop, months past and buttons, icons, colours started to stray into various sizes, looks, and hues.</li>
<li>The whole is great than the sum of its parts - Aristotle</li>
<li>How do you go about learning what a Design System is.</li>
<li>You could search the internet, find and article that will teach you … in 15 minutes.</li>
<li>You could find a similar, fully fledged Design System and apply it all for their needs. With little knowledge of what goes into it.</li>
<li>The most import thing consistency, connection, and speed in a startup.
<ul>
<li>Start with the brand - hack the consistency.
<ul>
<li>Make the brand a crucial part of your design system , because it can be a game changer.</li>
</ul>
</li>
<li>Leverage existing open source toolkits - hack for speed.
<ul>
<li>Leverage vs. Appropriation.</li>
<li>Don’t try to reinvent the wheel.</li>
</ul>
</li>
<li>It beings with you - hack for connection.
<ul>
<li>Look around, are you talking to the people next to you about it</li>
<li>Human connection is a superpower - it is the glue of your start up.</li>
</ul>
</li>
</ul>
</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Systems London 2019 - Lily Dart</title>
      <link href="https://www.alwaystwisted.com/articles/design-systems-london-2019-lily-dart.html"/>
      <updated>2019-11-15T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-systems-london-2019-lily-dart.html</id>
      <content type="html">
        <![CDATA[
        <ul>
<li>At Lloyds there are 350 designers, with 9000 developers. Getting folks to use the design system is a massive effort.</li>
<li>“I tend to define the design system as the official story of how your organisation designs and build products” - Brad Frost</li>
<li>Official Culture doesn’t necessarily mean Real Culture.</li>
<li>What words would you describe your team culture when asked in an interview situation?</li>
<li>What words would you describe your team culture when asked by a friend over dinner?</li>
<li>Are the answers the same?</li>
<li>Why does the difference matter in a Design System, because you won’t talk about the things you want to do but cannot because of the real culture.</li>
<li>The gulf between reality and practice make it hard for Design Systems to land.</li>
<li>When we lust over Design Systems it’s usually from companies that have the official and real culture overlapping a lot.</li>
<li>“If the design system goes against the grain of the company, you are going to get unstuck.” – Shaun Bent</li>
<li>“As we grew and matured as a design team, our newer design clashed with the older parts” – Emily Brick, Buzzfeed</li>
<li>At Lloyds they started to build things within the existing culture of the company. It was more sharing UIKits on a server. They moved to Sketch Libraries but also found they were maintaining the components in 3 different locations.</li>
<li>They wanted to provide detailed advice in using components, rather than creating the components in yet another format.</li>
<li>How to deal with cultural mismatch:
<ul>
<li>Make intentional compromises.</li>
<li>Challenge the status quo.</li>
<li>Pick your battles, and play the long game.</li>
</ul>
</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Systems London 2019 - Laura González</title>
      <link href="https://www.alwaystwisted.com/articles/design-systems-london-2019-laura-gonzlez.html"/>
      <updated>2019-11-15T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-systems-london-2019-laura-gonzlez.html</id>
      <content type="html">
        <![CDATA[
        <ul>
<li>The Guardian has a ton of layouts for different content and stories.</li>
<li>They didn’t really have a Design System and have started looking at creating one.</li>
<li>They had two subscription services needing the same pages - a great opportunity to join forces.</li>
<li>They didn’t have the resources to create a Design System, so they created a guerrilla design system.</li>
<li>Design is applying a ton of unwritten rules with writing a ton of CSS</li>
<li>Design System = Design as a System?</li>
<li>When building the subscriptions page - they could ‘copy and paste the CSS from figma’ but it doesn’t make sense, doesn’t use tokens and can easily fall apart.</li>
<li>The web is less of a garden and more of a battle ground</li>
<li>We need to make CSS is resilient and scales.</li>
<li>Design System = future-proofing - by sharing the same base core we can help the future.</li>
<li>The gaming industry are similar in they too have Design Systems for their game maps and layout.</li>
<li>How do developer a unique page as part of a system
<ul>
<li>find patterns</li>
<li>turn them into components</li>
<li>reuse, recycle, reiterate</li>
</ul>
</li>
<li>Writing more CSS is easier than talking to people.</li>
<li>If you have a website, you have a poorly documented design system already.</li>
<li>Converting the components of a page into a Storybook component library some guardian developers called it an ‘anti design system’ but it solved the goals of the subscriptions service pages.</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Systems London 2019 - Kathleen McMahon</title>
      <link href="https://www.alwaystwisted.com/articles/design-systems-london-2019-kathleen-mcmahon.html"/>
      <updated>2019-11-15T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-systems-london-2019-kathleen-mcmahon.html</id>
      <content type="html">
        <![CDATA[
        <ul>
<li>
<p>A self confessed ‘dev dinosaur’ it can feel overwhelming when there seems to be a new JavaScript every week.</p>
</li>
<li>
<p>They’re part of a small team so they had to focus on small things to start with</p>
</li>
<li>
<p>Business logic out, accessibility first in.</p>
</li>
<li>
<p>You Design System is a cookbook. A cookbook has a personality.</p>
</li>
<li>
<p>Design Systems and React</p>
<ul>
<li>“React fully supports building accessible website often by using standard HTML and CSS techniques.</li>
<li>React is a utensil.</li>
<li>You are the cook. You have to know the standards of HTML, CSS, and Javascript and what you need to do to make things accessible.</li>
</ul>
</li>
<li>
<p>Creating a component is like following a receipt start with high quality ingredients - HTML</p>
</li>
<li>
<p>It is very important to create ‘guard rails’ for your components to make sure developers are always using the accessibility feature you have built in for them.</p>
</li>
<li>
<p>Buttons performa an action on a page - should look and act like a button. Screenreader support comes ‘for free’ when using a .</p>
</li>
<li>
<p>Buttons should only receive inline elements as children. A not a</p>
<p>.</p>
</li>
<li>
<p>Inputs need label and error messages. Placeholder are <strong>NOT</strong> labels.</p>
</li>
<li>
<p>Make inputs a max character count of 80. Keep labels stacked close. Labels above input, errors below input.</p>
</li>
<li>
<p>Documentation. Those massive Design Systems in public are drool-worthy.</p>
</li>
<li>
<p>In a small team you need to include the documentation that is required to start.</p>
</li>
<li>
<p>Include helpful hints into your documentation. Show people how to properly implement a component. Component Do’s and Don’ts are essential</p>
</li>
<li>
<p>Include a dedicate page to accessibility resources.</p>
</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Systems London 2019 - Jon Reidy</title>
      <link href="https://www.alwaystwisted.com/articles/design-systems-london-2019-jon-reidy.html"/>
      <updated>2019-11-15T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-systems-london-2019-jon-reidy.html</id>
      <content type="html">
        <![CDATA[
        <ul>
<li>HSBC is different to the average start up, it’s 150 years old.</li>
<li>No one was thinking about Design Tokens and React Components then.</li>
<li>HSBC is bg, 250,000 staff in nearly 80 countries</li>
<li>The worlds biggest international bank</li>
<li>Lots of everything which leads to lots of fragmentation.</li>
<li>HSBC has had a design system in one way or another for the lsat 9 years</li>
<li>2017 they had a rebrand that allowed a big sweeping change in creating a global digital design system.</li>
<li>The HSBC Global Digital Design System is made of:
<ul>
<li>Design Language</li>
<li>Community</li>
<li>Design Thinking</li>
<li>Review and Alignment</li>
<li>Measurement and Performance</li>
<li>Tools</li>
</ul>
</li>
<li>The HSBC Global Digital Design System is part of their “digital DNA”.</li>
<li>You need a strong community
<ul>
<li>builds trust</li>
<li>creates communication channels</li>
</ul>
</li>
<li>Creative Hierarchy was found to be important.
<ul>
<li>roles and responsibilities</li>
<li>helps create harmony</li>
<li>easier communcations</li>
<li>faster decisions made</li>
</ul>
</li>
<li>The go from a top down bottom up approach with broad decisions coming from the top and evolution of things coming from the bottom</li>
<li>Tooling is key!
<ul>
<li>Decentralised</li>
</ul>
</li>
<li>The biggest challenge they found was the ego. In large companies it’s hard to ‘make your own mark’.</li>
<li>They’re currently looking at AI and Automation for the future of their Design System.
<ul>
<li>Labour intensive tasks</li>
<li>administration</li>
<li>reports-</li>
</ul>
</li>
<li>Project: Robot Chicken
<ul>
<li>Design REviews</li>
<li>Machine Learning</li>
<li>Self Service Base</li>
<li>Takes around 8 seconds to do a AI powered design review</li>
<li>It’s currently at MVP stage, hope to be ‘ready’ in about a year.</li>
</ul>
</li>
<li>He doesn’t think it will ever take away the creative requirement of a person - but AI and automation will allow for an explosion of ideas.</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Systems London 2019 - James and James</title>
      <link href="https://www.alwaystwisted.com/articles/design-systems-london-2019-james-and-james.html"/>
      <updated>2019-11-15T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-systems-london-2019-james-and-james.html</id>
      <content type="html">
        <![CDATA[
        <ul>
<li>Design Systems are literally everywhere, and everyone seems to have one.</li>
<li>The benefits of Design Systems sounds great, but where do you start?
<ul>
<li>A design system is a continuous approach not an end solution</li>
</ul>
</li>
<li>There are two big questions to ask
<ul>
<li>Do you need a Design System?
<ul>
<li>Don’t implement one because it is a big shiny buzzword</li>
<li>Work out what are the problems you re trying to solve by introducing one</li>
</ul>
</li>
<li>Are you ready for one?
<ul>
<li>How much resource is available,</li>
<li>What buy-in do you have
<ul>
<li>The business should know the benefits</li>
<li>The business should know the constraints</li>
</ul>
</li>
<li>Having the Skills
<ul>
<li>great developers and designers</li>
<li>have documentation</li>
<li>DevOps</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>Poor ownership can lead to
<ul>
<li>Disagreements over direction</li>
<li>incorrect additions</li>
<li>inconstant processes</li>
</ul>
</li>
<li>A centralised ownership created a bottleneck</li>
<li>Treat it as an open source project so everyone can help with it. This leads to better components through shared knowledge and more usage because of the shared ownership</li>
<li>But you still need a small core ownership, with a design system council
<ul>
<li>They have key responsibilities.
<ul>
<li>updates</li>
<li>roadmap</li>
<li>identify inconsistencies</li>
</ul>
</li>
</ul>
</li>
<li>Why Design Reviews?
<ul>
<li>Where should the component be built?</li>
<li>Are there existing components?</li>
<li>More than one team that need similar components</li>
</ul>
</li>
<li>Hold Knowledge sharing sessions.
<ul>
<li>What we wish we’d known
<ul>
<li>Ensure organisational understanding</li>
<li>understand impact</li>
<li>understand bottlenecks of centralised teams</li>
</ul>
</li>
</ul>
</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Systems London 2019 - Bernardo Raposo</title>
      <link href="https://www.alwaystwisted.com/articles/design-systems-london-2019-bernardo-raposo.html"/>
      <updated>2019-11-15T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-systems-london-2019-bernardo-raposo.html</id>
      <content type="html">
        <![CDATA[
        <ul>
<li>“Design Systems are 80-90% people stuff, 10-20% design/dev/tools stuff.” – Brad Frost</li>
<li>“A Design System is a language. If people are not speaking the same language, there will be nothing but confusion” – Alex</li>
<li>Design System is the documentation.</li>
<li>The Apple Human Interface Guidelines that is 35 years old”
<ul>
<li>General design principles</li>
<li>Principles of graphic communicatoin</li>
<li>A strategy for programming</li>
<li>Designing for disabled people</li>
<li>elements of the Desktop interface</li>
</ul>
</li>
<li>Design System is the code.</li>
<li>What about Code in design tools - <a href="https://airbnb.design/painting-with-code">Paint With Code</a></li>
<li>Design Is Code.</li>
<li><a href="https://www.github.com/seek-oss/playroom">Playroom</a></li>
<li>Design System Relationships are based on trust and being present.</li>
<li>Make Design Systems more open.</li>
<li>Make Design Systems more human.</li>
<li>We need different tools for this relationship between Designers and Developers
<ul>
<li>Interplay</li>
<li>Alva</li>
<li>UXPin Merge</li>
<li>Framer X</li>
<li>Builder X</li>
<li>Modulz</li>
</ul>
</li>
<li>Design System is the language.
<ul>
<li>Should we create a common format for design systems</li>
<li><a href="http://Diez.org">Diez.org</a></li>
<li>Storybook CSF</li>
<li>Avocode SDK</li>
</ul>
</li>
<li>Use the documentation as a starting point.</li>
<li>Add code to improve the design process.</li>
<li>Think about the people using the Design System.</li>
<li>Make Design open to everyone.</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Systems London 2019 - Anja Klüver</title>
      <link href="https://www.alwaystwisted.com/articles/design-systems-london-2019-anja-klver.html"/>
      <updated>2019-11-15T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-systems-london-2019-anja-klver.html</id>
      <content type="html">
        <![CDATA[
        <ul>
<li>Everything they work on has to be measurable, including the Design System.</li>
<li>The business case for the design system needs to be addressed.</li>
<li>to make sure the company adopt it, as it’s an organisational transform and change.</li>
<li>The need for a Design System is a need for efficiency of scale.</li>
<li>As products become more complex over time there is a curve where static things will suffer and there’s a need for more easy-to-update things from a Design System.</li>
<li>Selling a Design System – “A successful design system delivers cohesive, scaleable features in a way that’s efficient for both design and development”.</li>
<li>What is the economic impact of using a Design System. Design generates ROI - for IBM it saved them $20.6m and reduced the risk cost by $18.6m.</li>
<li>A client they have been worked with they had to go through three levels of management to discuss the business needs for a Design System.
<ul>
<li>30% cash saving.</li>
<li>10-30% increase in conversion.</li>
<li>10-30% increate in customer loyalty.</li>
</ul>
</li>
<li>Legacy development was often in a ‘waterfall’ with a Design System you save time to market and cost because of the agile process that is indicative of creating one.</li>
<li>A Design System allows for triggering innovation, faster prototyping, increased usability and adoption, and brand perception.</li>
<li>How to measure?
<ul>
<li>There’s ‘quant’ - time and resource costs, the rework and repetition, the tech. and design debt. There’s also time to market, scalability, adoption and loyalty.</li>
<li>There’s ‘qual’ - brand equity, innovation, brand perception, team happiness, client NPS score.</li>
</ul>
</li>
<li>Peoples Adoption Hurdles with starting a Design System:
<ul>
<li>culture and behaviour.</li>
<li>social-technical.</li>
<li>totalitarian and inflexible.</li>
<li>exploration and divergence.</li>
</ul>
</li>
<li>You need to deliver measured benefits step–by–step to keep up with adoption
<ul>
<li>Make it user first.</li>
<li>Start small.</li>
<li>Make sure the team is empowered and there’s a consent to the system.</li>
<li>Demo the benefits</li>
<li>Manage the perceptions</li>
<li>Make sure it has shared ownership</li>
</ul>
</li>
<li>Four principles for a design system
<ul>
<li>Inspire and Inform - start with a pilot project, a new project</li>
<li>Create - Bring methodology alive, show and tell.</li>
<li>Consult and Educate - adoption workshops</li>
<li>Collaborate and Manage - embed and define the governance.</li>
</ul>
</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Creating Utility Classes with Design Tokens using Sass</title>
      <link href="https://www.alwaystwisted.com/articles/creating-utility-classes-with-design-tokens-using-sass.html"/>
      <updated>2019-07-22T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/creating-utility-classes-with-design-tokens-using-sass.html</id>
      <content type="html">
        <![CDATA[
        <p>At the start of a Design System, there’s a chance that things can move pretty fast.</p>
<p>There may be more than one or two people working on creating components (if you’re lucky). You might want to prototype things quickly with “throwaway code”. When it matures there may be certain use cases where you need a slight adjustment here and there for a particular component to work, or you may not be able to include the components you need as you would hope to.</p>
<p>After creating a set of <a href="https://css-tricks.com/what-are-design-tokens/">Design Tokens</a> for my clients Design System I looked at how best we can quickly create some additional utility classes for the various &quot;exceptions to the rule&quot; mentioned above. We needed something that would work automatically, programmatically, and with as little human interaction as possible once it was set up.</p>
<h2 id="using-sass-in-2019" tabindex="-1">Using Sass in 2019</h2>
<p>The project was already using Sass (a decision that was made after some research (that might be another article, whenever I find the time)) and I have <a href="2014-03-06-even-better-each-loops-with-sass-33.html">previously used loops</a> and <a href="https://sass-lang.com/documentation/interpolation">interpolation</a> so I knew we could create these classes with a pre-processor language that is already in place without resorting to something else, an extra dependency.</p>
<p>As we’re using Sass already we are outputting the Design Tokens using <a href="https://github.com/salesforce-ux/theo">Theo</a> to generate files of Sass <a href="https://sass-lang.com/documentation/variables">variables</a> and <a href="https://sass-lang.com/documentation/values/maps">maps</a> that are needed.</p>
<p>To create our utility classes we would need a Sass <a href="https://sass-lang.com/documentation/at-rules/mixin">@mixin</a> that would use the class selector to inform the initial naming of the created rule sets. An <a href="https://sass-lang.com/documentation/at-rules/control/each">@each rule</a> to loop through the Sass maps, and an additional <code>$prefix</code> variable to allow us to create classnames.</p>
<h2 id="design-tokens-and-maps" tabindex="-1">Design Tokens and Maps</h2>
<p><a href="https://github.com/salesforce-ux/theo">Theo</a> takes your Design Tokens that can be authored in a <code>.yml</code> or <code>.json</code> format and then can convert them into a Sass map, amongst a lot of other formats.</p>
<p>An example Sass map that we are going to use could look something like this:</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$ds-color-map</span></span><span class="token punctuation">:</span> <span class="token punctuation">(</span>
  <span class="token property">green-100</span><span class="token punctuation">:</span> #c8e6c9<span class="token punctuation">,</span>
  <span class="token property">green-200</span><span class="token punctuation">:</span> #a5d6a7<span class="token punctuation">,</span>
  <span class="token property">green-300</span><span class="token punctuation">:</span> #81c784<span class="token punctuation">,</span>
  <span class="token property">green-400</span><span class="token punctuation">:</span> #66bb6a<span class="token punctuation">,</span>
  <span class="token property">green-500</span><span class="token punctuation">:</span> #4caf50<span class="token punctuation">,</span>
  <span class="token property">green-600</span><span class="token punctuation">:</span> #43a047<span class="token punctuation">,</span>
  <span class="token property">green-700</span><span class="token punctuation">:</span> #388e3c<span class="token punctuation">,</span>
  <span class="token property">green-800</span><span class="token punctuation">:</span> #2e7d32<span class="token punctuation">,</span>
  <span class="token property">green-900</span><span class="token punctuation">:</span> #1b5e20<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="creating-the-%40each-loop" tabindex="-1">Creating the @each loop</h2>
<p>In the above map with have the key/value pair of the name of the colour and the hex code that represents it. To create an <code>@each</code> rule we would need to write something like:</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.u-color </span><span class="token punctuation">{</span>
  <span class="token keyword">@each</span> <span class="token selector"><span class="token variable">$name</span>, <span class="token variable">$hex</span> in <span class="token variable">$ds-colors-map</span> </span><span class="token punctuation">{</span>
    <span class="token property"><span class="token variable">#{$name}</span></span><span class="token punctuation">:</span> <span class="token variable">$hex</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Using the <code>@each</code> rule we go through key/value pairs of <code>$ds-colors-map</code> and get the key: <code>$name</code> and the value: <code>$hex</code>. We then use these variables to create the declaration inside the rule. This <code>@each</code> rule makes use of interpolation to turn the <code>$name</code> variable into property inside the declaration.</p>
<p>But this would only create a list of CSS colour rules within the ruleset like:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.u-color</span> <span class="token punctuation">{</span>
  <span class="token property">green-100</span><span class="token punctuation">:</span> #c8e6c9<span class="token punctuation">;</span>
  <span class="token property">green-200</span><span class="token punctuation">:</span> #a5d6a7<span class="token punctuation">;</span>
  <span class="token property">green-300</span><span class="token punctuation">:</span> #81c784<span class="token punctuation">;</span>
  <span class="token property">green-400</span><span class="token punctuation">:</span> #66bb6a<span class="token punctuation">;</span>
  <span class="token property">green-500</span><span class="token punctuation">:</span> #4caf50<span class="token punctuation">;</span>
  <span class="token property">green-600</span><span class="token punctuation">:</span> #43a047<span class="token punctuation">;</span>
  <span class="token property">green-700</span><span class="token punctuation">:</span> #388e3c<span class="token punctuation">;</span>
  <span class="token property">green-800</span><span class="token punctuation">:</span> #2e7d32<span class="token punctuation">;</span>
  <span class="token property">green-900</span><span class="token punctuation">:</span> #1b5e20<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>What we want is to generate individual class selectors to hold each key/value pair.</p>
<h2 id="making-the-%40mixin" tabindex="-1">Making the @mixin</h2>
<p>To get Sass to generate the utility classes for our Design Tokens using the Sass maps. We need to create a <code>@mixin</code> and slightly change the <code>@each</code> rule. Before we look into that we should think about the structure of the class selectors we are wanting to create. Using colour as the example I want to create a set of CSS rules that look like this:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.u-color-text-green-100</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #c8e6c9<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>With a <code>@mixin</code> we need to be able to create part of the <code>selector</code> of a rule so that it include <code>--</code>. We also need the correct key: <code>$name</code> as part of the <code>selector</code>, and value: <code>$hex</code> as the declarations <code>value</code>.</p>
<p>We can make use of Sass’ interpolation to help us with this, so that we can generate the correct naming conventions for the class selectors. Inside the <code>@mixin</code> we can add our working <code>@each</code> rule like this:</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@mixin</span> <span class="token selector">color-utilities </span><span class="token punctuation">{</span>
  <span class="token keyword">@each</span> <span class="token selector"><span class="token variable">$name</span>, <span class="token variable">$hex</span> in <span class="token variable">$ds-colors-map</span> </span><span class="token punctuation">{</span>
    <span class="token selector"><span class="token parent important">&amp;</span>-<span class="token variable">#{$name}</span> </span><span class="token punctuation">{</span>
      <span class="token property">color</span><span class="token punctuation">:</span> <span class="token variable">$hex</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>When called this <code>@mixin</code> will go through the <code>$ds-colors-map</code> we have and generate a class selector using the parent selector name using the <code>&amp;</code>, we add the <code>--</code> to then separate the parent selector from the key: <code>$name</code> of the pair in the map and then print the value: <code>$hex</code> as the value in the declaration. When invoked in a class like:</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.u-color-text </span><span class="token punctuation">{</span>
  <span class="token keyword">@include</span> <span class="token function">color-utilties</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>We get an compiled output like:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.u-color-text-green-100</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #c8e6c9<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.u-color-text-green-200</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #a5d6a7<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.u-color-text-green-300</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #81c784<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.u-color-text-green-400</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #66bb6a<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.u-color-text-green-500</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #4caf50<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.u-color-text-green-600</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #43a047<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.u-color-text-green-700</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #388e3c<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.u-color-text-green-800</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #2e7d32<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.u-color-text-green-900</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #1b5e20<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="extending-the-%40mixin" tabindex="-1">Extending the @mixin</h2>
<p>That works great but it’s not very flexible. I want to generate rules for each way colour can be used in CSS. Not only for text but for borders and backgrounds like this:</p>
<pre class="language-scss"><code class="language-scss"><span class="token comment">// text colours</span>
<span class="token selector">.u-color-text-green-100 </span><span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #c8e6c9<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// background colours</span>
<span class="token selector">.u-color-background-green-100 </span><span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> #c8e6c9<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// border colours</span>
<span class="token selector">.u-color-border-green-100 </span><span class="token punctuation">{</span>
  <span class="token property">border-color</span><span class="token punctuation">:</span> #c8e6c9<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>To do this we can modify the <code>@mixin</code> we have created to allow us to set the <code>property</code> that would be inside the declaration. We need to add an argument to our <code>@mixin</code> that will set this property and then use that argument where needed. As it’s the <code>property</code> of the declaration that is needs to be changed we can add a it to our <code>@mixin</code> along with a default so the first line is like:</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@mixin</span> <span class="token function">color-utilities</span><span class="token punctuation">(</span><span class="token property"><span class="token variable">$property</span></span><span class="token punctuation">:</span> <span class="token string">'color'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></code></pre>
<p>We then need to use that <code>$property</code> argument as our property in the declaration using interpolation, so that the whole <code>@mixin</code> looks like this:</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@mixin</span> <span class="token function">color-utilities</span><span class="token punctuation">(</span><span class="token property"><span class="token variable">$property</span></span><span class="token punctuation">:</span> <span class="token string">'color'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">@each</span> <span class="token selector"><span class="token variable">$name</span>, <span class="token variable">$hex</span> in <span class="token variable">$vf-colors-map</span> </span><span class="token punctuation">{</span>
    <span class="token selector"><span class="token parent important">&amp;</span>-<span class="token variable">#{$name}</span> </span><span class="token punctuation">{</span>
      <span class="token property"><span class="token variable">#{$property}</span></span><span class="token punctuation">:</span> <span class="token variable">$hex</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Doing this allows us to include the <code>@mixin</code> in the 3 types of colour classes we want to create:</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.u-color-text </span><span class="token punctuation">{</span>
  <span class="token keyword">@include</span> <span class="token function">color-modifiers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.u-color-background </span><span class="token punctuation">{</span>
  <span class="token keyword">@include</span> <span class="token function">color-modifiers</span><span class="token punctuation">(</span>background-color<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.u-color-border </span><span class="token punctuation">{</span>
  <span class="token keyword">@include</span> <span class="token function">color-modifiers</span><span class="token punctuation">(</span>border-color<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Which will generate the a list of rules like I have mentioned above.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.u-color-text-green-100</span> <span class="token punctuation">{</span>
  <span class="token property">color</span><span class="token punctuation">:</span> #c8e6c9<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.u-color-background-green-100</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> #c8e6c9<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.u-color-border-green-100</span> <span class="token punctuation">{</span>
  <span class="token property">border-color</span><span class="token punctuation">:</span> #c8e6c9<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="what-next%3F" tabindex="-1">What next?</h2>
<p>Now we can create an individual rule for each of the colours that our Design Tokens has for text, background and border but Design Tokens are more than colour. With a few modifications to the <code>@mixin</code> created here we can then do this with any typographic styles and spacing values we have.</p>
<p>I created a CodePen that includes the <code>@mixins</code> that can be used to create those additional utility classes.</p>
<p>See the Pen <a href="https://codepen.io/sturobson/pen/oKXBxL/">Utility Class Sass Generators</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>) on <a href="https://codepen.io">CodePen</a>.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Curating A Design System Newsletter</title>
      <link href="https://www.alwaystwisted.com/articles/curating-a-design-system-newsletter.html"/>
      <updated>2019-07-01T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/curating-a-design-system-newsletter.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="this-ain%E2%80%99t-my-first-rodeo." tabindex="-1">This ain’t my first rodeo.</h2>
<p>For a couple of years I ran an email newsletter for all things Sass, creating a weekly newsletter sharing articles, tutorials, code, videos, pretty much anything I found interesting about Sass.</p>
<p>Giving myself the task of sending this out weekly though had three things to it’s detriment.</p>
<p>The first was having to find 8-10 links per week. Often I would be adding items to make up the numbers and this led to several similar items and sometimes subpar items being included.</p>
<p>The second was adding the items. I was using Mailchimp with a custom design for the newsletter. I would bookmark the items as I went through my week and then copy and paste them into the relevant HTML snippets and adding a blurb about the item before the newsletter hit the inboxes.</p>
<p>The third was my health. Forcing myself on a release date and time of every Tuesday at 10am made me have to continually do the legwork to get it released.</p>
<p>The third one was where I just gave up. I stopped completely.</p>
<p>Roll on a couple of years and I started working on more projects that were wholly related to what’s now often termed “Design Systems”.</p>
<p>I was reading everything I could find about the myriad of things that make up a “Design System” and got to a point where I felt I should start sharing these.</p>
<p>I should start a new newsletter.</p>
<h2 id="adding-constraints" tabindex="-1">Adding Constraints</h2>
<p>Knowing what happened the first time I decided to run a newsletter I gave myself some constraints:</p>
<h3 id="curated" tabindex="-1">Curated</h3>
<p>As I’ve mentioned at some points I was adding items to the Sass News email just to fill the space. This time around I decided I would only add things I felt others would benefit from and things that offered something new to the conversation. I didn’t want to include the 40th article on “What is a Design System”.</p>
<p>I still read through these, if they didn’t add anything substantial to the conversation they didn’t get into the email.</p>
<h3 id="sporadic-by-nature" tabindex="-1">Sporadic by nature</h3>
<p>I didn’t want to tie it down to a weekly publication cycle and by going with the ‘curated’ idea on what is included I allowed myself to decide when to ‘hit publish’. When I felt it was ready, not when it was 10am on an given Tuesday.</p>
<h3 id="no-blurbs" tabindex="-1">No blurbs</h3>
<p>Sometimes the titles of items don’t really give to much away and this could stop people clicking, but with the two constraints above affecting what goes in it was also my time being saved.</p>
<h2 id="where-am-i-looking%3F" tabindex="-1">Where am I looking?</h2>
<p>To make a (what I hope to be) useful newsletter I read, watch, listen to a plethora of resources on Design Systems almost everyday, but where do they come from?</p>
<h3 id="rss" tabindex="-1">RSS</h3>
<p>I have an RSS feed that not only subscribes to several people, companies and ‘magazines’ int the industry pulls in feeds from Medium for:</p>
<ul>
<li>Design Systems</li>
<li>Pattern Libraries</li>
<li>Styleguides</li>
<li>Documentation</li>
</ul>
<p>Sometimes the Medium RSS feeds are chock-full of things, and I am seeing an increase in this as the weeks go on.</p>
<p>To note, if I find something via a Medium RSS feed and find that the author has posted it on their own blog, I link to that instead.</p>
<h3 id="twitter" tabindex="-1">Twitter</h3>
<p>I have several saved searches that I look through a couple of times a day, these are the same terms as the list of RSS feeds from Medium.</p>
<h3 id="google" tabindex="-1">Google</h3>
<p>I search for “Design Systems” in Googles search engine, picking the last week, or last 24 hours (depending on how long I think it was when I did it last. This search is also used in the Google Search video section.</p>
<h2 id="about-that-emoji" tabindex="-1">About that emoji</h2>
<p>Essentially the icons (kind of) relate to the sections: articles, tools and tutorials interesting reads with things like slide decks, videos, and podcasts having their own emojis. Leaving a heart for actual design systems I have found.</p>
<p>There’s really nothing more to the use of emoji than that. Initially I went with no categories at all, but felt they would help people clicking on what is just the title. I hope adding a emoji used helps playfully inform readers that they’re about to click on a video rather than an article.</p>
<p>Those Warning Signs</p>
<hr>
<p>Some time ago I was going through the backlog of around 90 unread articles on Design Systems. About 80 of those were Medium articles and about 40 of those took me to either their user-hostile “you ready a lot and we like that” pop-up or their money-grabbing “you’ve read lots this month, pay us to read some more.”, it turns out that Medium only likes you reading things when you give money to do so.</p>
<p>Therefore I’ve started to add a little warning notice to each article that’s on Medium. There are people that probably won’t click on it, but there are people that will (and do) and I just want to let them know they might actually be able to read it.</p>
<p>If I ever find an article that has been syndicated to Medium where, generally, the writer publicises the original url I use that (note: with the various Medium pop-ups it is better to put that link at the top of your article).</p>
<p>I know some people might feel begrudged with this, “why shouldn’t I expect to get some income from what I share?”, I don’t begrudge you from wanting to make a little bit (I assume it’s a little bit) of money from your efforts. I just do not like Medium’s hostile environment for the reader.</p>
<h2 id="what-does-that-summary-line-mean%3F" tabindex="-1">What does that summary line mean?</h2>
<p>From “…the room was humming harder, as the ceiling flew away.” to “For you there might be another star, but through my eyes the light of you it’s all I see.” every issue of the newsletter gains a unique summary. As part of publishing a newsletter using <a href="https://www.curated.co">curated</a> you have to provide a summary text as well as a title. So I’ve borrowed a concept I think I first saw on either Raw! or Total Guitar.</p>
<p>Every time I come to hit the publish button, I now look to the last song that I was listening to on Spotify, pick a line or two from the lyrics and use that as the summary.</p>
<h2 id="if-it%E2%80%99s-curated%2C-isn%E2%80%99t-it-biased%3F" tabindex="-1">If it’s curated, isn’t it biased?</h2>
<p>Maybe, I hope it isn’t. I try and include things that I really think others would benefit from rather than “what’s hot on twitter” in the design systems spectrum.</p>
<p>I hope through the various sources I find articles exposes articles that others may miss, or never see. I am reading several “What is a Design System?” posts a week so you don’t really have to. If I feel an article has something new, unique, or different to share. That’s a surefire way of it being added into the newsletter.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Patterns Day 2019 - Varya Stepanova</title>
      <link href="https://www.alwaystwisted.com/articles/patterns-day-2019-varya-stepanova.html"/>
      <updated>2019-06-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/patterns-day-2019-varya-stepanova.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="a-practical-guide-to-building-your-design-system-infrastructure" tabindex="-1">A practical guide to building your design system infrastructure</h2>
<p>In <a href="https://twitter.com/varya_en">Varya’s</a> talk for Patterns Day 2019 they discussed a practical way of applying technologies like React with your design system.</p>
<h3 id="design-system-at-elisa" tabindex="-1">Design System at Elisa</h3>
<ul>
<li>Library of css components</li>
<li>Libraries of React components</li>
<li>UI kit in Sketch</li>
<li>Shared tools and practices</li>
<li>Great design community</li>
<li>World-class front-end teams</li>
</ul>
<h3 id="what-is-design-systems%3F" tabindex="-1">What is Design Systems?</h3>
<p>Often it is termed as purely component libraries, for Varya it means:</p>
<ul>
<li>shared practices (like component libraries and documentation).</li>
<li>tools (for developers and designers to keep a standardised design system).</li>
<li>processes.</li>
<li>community.</li>
</ul>
<h3 id="to-react-or-not-react%3F" tabindex="-1">To React or Not React?</h3>
<ul>
<li>React Styleguidist and Storybook are seen as things for React Libraries, great tools that can have a component playground and also be used as a documentation site.</li>
<li>Yet, they can also be used for not just React.</li>
<li>With Styleguidist, you can create the component by adding the HTML in a markdown file for the component.</li>
<li><a href="https://twitter.com/alexmuench/status/1111297292215246850">Alex</a></li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Patterns Day 2019 - Una Kravets</title>
      <link href="https://www.alwaystwisted.com/articles/patterns-day-2019-una-kravets.html"/>
      <updated>2019-06-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/patterns-day-2019-una-kravets.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="the-problem-with-legos-%26-system-at-scale" tabindex="-1">The Problem With Legos &amp; System at Scale</h2>
<p>In <a href="https://twitter.com/una">Una’s</a> talk they discussed how Design Systems can fail and what we can do to stop that.</p>
<ul>
<li>Design Systems Support User Needs</li>
<li>But not all design systems are successful</li>
<li>Reasons why Design Systems fail</li>
<li>These five elements are really key:
<ul>
<li>Investment - small, incremental, continuous change is necessary for a design system to succeed as a a product grows and adapts.</li>
<li>Communication - creating continuous and open dialog between designers developers, project mangaers and end-users.</li>
<li>Buy-In - A system needs support to succeed.</li>
<li>Solid Architecture - What happens when nobody is using today’s frameworks anymore? What’s the next thing?</li>
<li>Frictionless - If a system is more difficult to use than the current workflow, nobody will want to adopt it.</li>
</ul>
</li>
<li>Building a design system is like building with lego blocks.</li>
<li>When you really start to scale the system - the lego analogy breaks down.</li>
<li>Lego has custom pieces doing one thing and that one thing really well.</li>
<li>With Lego sets you cannot build a T-Rex lego set with a car lego set.</li>
<li>A Lego set will never change.</li>
<li>You could use a part from a different set, but it would look odd.</li>
</ul>
<h3 id="design-is-ever-changing." tabindex="-1">Design is ever-changing.</h3>
<ul>
<li>
<p>Designs change.</p>
</li>
<li>
<p>You need to write the CSS for the new trends.</p>
</li>
<li>
<p>We moved from skeuomorphism to flat design using the technology available to create the designs.</p>
</li>
<li>
<p>Typography changes, the system needs to keep up</p>
</li>
<li>
<p>Form Follows Function</p>
</li>
<li>
<p>Design Follows Technology</p>
</li>
</ul>
<p>Just as design changes, design systems technology changes. Which is great, but can also be a challenge to how your Design System scales.</p>
<ul>
<li>A Unified Design Spec
<ul>
<li>guidelines, guidelines, guidelines</li>
<li>in Material each component has specific guidelines as well as generic guidelines.</li>
<li>It’s nice to have robust documentation, but you need the tooling to work with the spec.</li>
</ul>
</li>
<li>Tooling
<ul>
<li>a colour picker on Material allows you to define a theme across your product</li>
<li>a shape tool allows you to define the borders on all relevant components.</li>
<li>Google Fonts - an excellent resource of free typefaces</li>
<li>With the tooling in place you can move to components</li>
</ul>
</li>
<li>Components
<ul>
<li>Material provides components you can use within your material project or individually.</li>
</ul>
</li>
<li>Theming
<ul>
<li>Material provides the flexibility for brands to maintain their style on top of the components from Material, so everything doesn’t ‘just look like Google’.</li>
</ul>
</li>
</ul>
<p>In the end the design team found three sub-systems for theming that help build systematic expression of your product</p>
<ul>
<li>Typography</li>
<li>Colour</li>
<li>Shapes</li>
</ul>
<p>Colour:</p>
<ul>
<li>colour effects text and background of your application</li>
<li>primary and secondary colours</li>
<li>Allocate semantic meaning to your core application.</li>
<li>With the Sass variables or CSS custom properties you can easily see the difference in the components.</li>
</ul>
<p>Typography:</p>
<ul>
<li>think about the shape of the type you’re using</li>
<li>can be easily imported via Sass.</li>
</ul>
<p>Shape:</p>
<ul>
<li>strong difference in shape can be used to direct attention.</li>
<li>asymmetric shapes can help emphasise certain aspect of the UI</li>
<li>shape can be used to communicate a component state.</li>
<li>CSS Houdini allows you to tell the browser how it should read your CSS via JavaScript.</li>
<li>Houdini allows you to create shapes that are not in the CSS spec (yet).</li>
</ul>
<h3 id="overrides" tabindex="-1">Overrides</h3>
<ul>
<li>nobody needs a custom component</li>
<li>… everybody needs a custom component.</li>
<li>When we provide theming, some times what is available is not enough.</li>
<li>In Material you can use Sass mixins to override the CSS</li>
</ul>
<blockquote>
<p>CSS is Not the Enemy.</p>
</blockquote>
<p><a href="http://glitch.com/~material-theme-builder">Material Theme Builder</a>.</p>
<p>When building your own themes using Material keep in mind accessibility, colour contrast is on you to get right.</p>
<p>If we stifle the needs of users, the design system will not be used.</p>
<p>Material, like any component library is a work in progress.</p>
<p>Design Systems are way to complex to keep comparing them to Lego.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Patterns Day 2019 - Inayaili de León</title>
      <link href="https://www.alwaystwisted.com/articles/patterns-day-2019-inayaili-de-len.html"/>
      <updated>2019-06-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/patterns-day-2019-inayaili-de-len.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="5-untruths-about-design-systems" tabindex="-1">5 untruths about design systems</h2>
<p>In their presentation at Patterns Day 2019, <a href="https://www.twitter.com/yaili">Yaili</a> talked about the untrue truths around Design Systems.</p>
<ul>
<li>
<p>Worked on Design Systems for both product and within agencies.</p>
</li>
<li>
<p>Has seen the mistakes that have been made.</p>
</li>
<li>
<p>When people talk about Design Systems - they often talk about the beautiful public sites available.</p>
</li>
<li>
<p>Then you see blogposts, podcasts, videos telling us how they figured things out</p>
</li>
<li>
<p>Then we look at our design systems and see the mess.</p>
</li>
<li>
<p>What you see in a public design system is a facade.</p>
</li>
<li>
<p>In reality, things are ugly, unfinished with tape and gum holding things together.</p>
<p>You’re not alone in having an imperfect system with documentation people don’t follow, with people ignoring the system exists altogether. No-one has it all figured out. No-one.</p>
<h3 id="untruth-%231" tabindex="-1">Untruth #1</h3>
<p>“Everyone loves and understands our work.”</p>
<p>“Some people hate us, and many don’t know what we’re trying to do.”</p>
<p>By explaining it to others in the company as “Do you know Google’s Material UI” doesn’t work.</p>
<p>What works is to sell the system, adapting to the different needs and requirements of the different teams in the company. How things would change, and what would get easier when you use the Design System.</p>
<p>You want to get from “Why am I wasting my time on this?” to “When can I start to use it?</p>
<h3 id="untruth-%232" tabindex="-1">Untruth #2</h3>
<p>“Our documentation is always up to date.”</p>
<p>“We don’t always have the time to document things.”</p>
<ul>
<li>When you look at the ‘faced’ you can see things like the nice grids, icons, and typography.</li>
<li>The truth is there are a lot of components that are used on sites now that are not documented and some that you may not even know about.</li>
<li>Working on a Design System is like a train that never reaches its destination. It just stops once in a while.</li>
<li>There is work we know that needs to be done, but nobody is asking for it.</li>
<li>Make time to improve things bit by bit.
<ul>
<li>Decide on a holistic structure.</li>
<li>A documentation page structure could have: Examples, Usage, Anatomy, Developer Guidance, API.</li>
</ul>
</li>
</ul>
<h3 id="untruth-%233" tabindex="-1">Untruth #3</h3>
<p>“Everyone works together in harmony.”</p>
<p>“We block each other all the time.”</p>
<ul>
<li>This does not just the members of the Design Systems team.</li>
<li>People will go ahead and just build something that matches their needs</li>
<li>You need to work on if patterns being created are new, or can be extended from existing components.</li>
<li>We shouldn’t block people from using the system, but should have process in place to improve the system.</li>
<li>You need to be comfortable in the knowledge that a Design Systems team will work slower than a ‘features’ team.</li>
</ul>
<h3 id="untruth-%234" tabindex="-1">Untruth #4</h3>
<p>“no one ever needs custom components”</p>
<p>“someone needs a custom component every day”</p>
<ul>
<li>It can be considered too soon to add a new component.</li>
<li>There might not be the time to create a shared solution</li>
<li>“I would like it if no-one asked for a new component”</li>
<li>The relationship between a product and a design system team is like a ‘push and pull’</li>
<li>If the product didn’t try new things, it would eventually become stale.</li>
<li>But if every change was accepted, you would be in a mess.</li>
<li>Make new things, think outside the box but be in the knowledge that it might not actually change what is within the design system</li>
</ul>
<p>It’s a balancing act. If all you do is accept all the proposals, you’re not doing a good job of maintaining a solid foundation in a Design System. The quality of work is going to suffer. If you say no to every request for change. People will just stop coming to the Design System. They will think that no-one is listening and that it is not for them.</p>
<p>Each new request needs to be within the context of the system.</p>
<h3 id="untruth-%235" tabindex="-1">Untruth #5</h3>
<p>“We validate everything.”</p>
<p>“Most times we push to the system without testing.”</p>
<ul>
<li>Sometimes there is not the time to get things through the entire process of testing, auditing, etc.</li>
<li>This goes back to being slow with the Design System.</li>
<li>You need to have conversations about what you’re working on</li>
<li>You need to build it</li>
<li>You need to continually improve it</li>
<li>You need to document it</li>
<li>You need to test it</li>
<li>Think of ways you can get other people to help with this process to validate things.</li>
<li>How can we make this true?
<ul>
<li>make a rule that a component is 100% valid until it has user-tested feedback.</li>
<li>you can have a label in your documentation that it needs testing</li>
<li>have regular catch ups with your testers to get them to include new components in their tests</li>
<li>work closely with the teams implementing the components to see the good and the bad points of them trying to use the Design System.</li>
</ul>
</li>
</ul>
</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Patterns Day 2019 - Heydon Pickering</title>
      <link href="https://www.alwaystwisted.com/articles/patterns-day-2019-heydon-pickering.html"/>
      <updated>2019-06-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/patterns-day-2019-heydon-pickering.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="flexbox-holy-albatross" tabindex="-1">Flexbox Holy Albatross</h2>
<p>In their post-lunch talk at Patterns Day 2019, <a href="https://www.heydonworks.com">Heydon</a> talked about the flexbox holy albatross layout pattern.</p>
<p><a href="http://www.heydonworks.com/article/the-flexbox-holy-albatross">The Flexbox Holy Albatross</a></p>
<p>The Flexbox Holy Albatros, breaking it down:</p>
<ul>
<li>
<p>Flexbox, the CSS layout. A way of arranging boxes inside of other boxes.</p>
<ul>
<li>We also have grid, but flexbox is not superseded by grid</li>
</ul>
</li>
<li>
<p>Holy, as in Holy Grail, wanted to find a solution to a specific layout problem in web development</p>
</li>
<li>
<p>Albatross, an allusion to a famous rap by Sammy C. It’s in the name, because it took a long time to solve the problem.</p>
</li>
<li>
<p>The problem, a basic layout with a parent that has child elements, where flexbox fills the space with the child.</p>
</li>
<li>
<p>When you create a basic flexbox layout, you have <code>flexbox: wrap;</code> by default where a widow child element would fill the rest of the available space.</p>
</li>
<li>
<p>The problem is, that <code>flexbox: wrap;</code> the child item, to a user, is treated differently, because it looks different.</p>
</li>
<li>
<p>What if we could bypass the stage, where a widowed child element takes the full-width, but without breakpoints.</p>
</li>
</ul>
<blockquote>
<p>“Why not use breakpoints?”</p>
<p>“No.”</p>
</blockquote>
<ul>
<li>Pertinently, media queries are a hack. They don’t work with design systems, they don’t need to be in design systems.</li>
<li>The media is constant, but with media queries but the context is not.</li>
<li>What about using container queries? Nope.</li>
<li>We could use JengaScript, named because of it’s way of handling errors. If you write an error, or somebody else does - it won’t work.</li>
<li>There could be use of resize observer, note - this only handles pixels. not ems, rems, ch, etc.</li>
</ul>
<p><a href="http://www.heydonworks.com/article/the-flexbox-holy-albatross-reincarnated">The Flexbox Holy Albatross Reincarnated</a></p>
<ul>
<li>The layout has to make the decision, kinda like a boolean, which CSS doesn’t have. This can be done with CSS custom properties and the cascade which can “turn things off and on”.</li>
<li>max-width always beats width, similar with min-width and width.
<ul>
<li><a href="https://codepen.io/hteumeuleu/pen/VaZgqg">The Fab Four Technique</a></li>
</ul>
</li>
<li>If you have a negative flex-basis - it will default to zero.</li>
<li>if we wanted gutters we could use <code>gap</code> but this is (currently) only supported in FireFox.</li>
<li>You could create gutters with margins, but this could break unless you add more declarative rules.</li>
<li>So, add margins to everything, and then you can remove from it, as you’re surprising the negative values.</li>
<li>Bonus: we can use <a href="https://alistapart.com/article/quantity-queries-for-css/">quantity queries</a>. This allows the browser to work out what it needs to do with styling child elements, but without using media queries.</li>
</ul>
<blockquote>
<p>“You want to be your browsers mentor, not it’s micro manager”</p>
</blockquote>
<p><a href="https://every-layout.dev">Every Layout</a></p>
<ul>
<li>simple layouts, that can be built upon each other to create a component.</li>
<li>the layouts are using Web Components, so you can drop them into things like Vue, Preact, etc.</li>
<li>they feature ‘getters’ and ‘setters’, sensible defaults with composition over inheritance.</li>
<li>Web Components doesn’t show its CSS to the DOM - there is a fork of JSDOM that can do this using a transform in 11ty, and you need to remove ShadowDOM &gt; creates a unique string of all the styles and that can be added to the HTML.</li>
<li>From CSS into JavaScript into E-HTML into CSS into HTML.</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Patterns Day 2019 - Emil Björklund</title>
      <link href="https://www.alwaystwisted.com/articles/patterns-day-2019-emil-bjrklund.html"/>
      <updated>2019-06-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/patterns-day-2019-emil-bjrklund.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="meandering-towards-design-systems" tabindex="-1">Meandering towards Design Systems</h2>
<p>In the last talk of the day, <a href="https://twitter.com/thatemil">Emil</a> discusses how the industry moved towards Design Systems</p>
<ul>
<li><a href="https://blog.natbat.net/post/46614243624/css-systems">CSS Systems for writing maintainable CSS by Natalie Downe</a></li>
<li>We have things we build - style guides, pattern libraries - and previously Design System seemed something that we built.</li>
<li>To most they can still mean style guides and pattern libraries.</li>
<li>We can all, in this room, agree that they more complex than “How to build a design system in React?”</li>
<li>Donella Meadows - systems thinking — “A set of related components that work together in a particular environment to perform whatever functions are required to achieve the systems’ objective.”</li>
<li>“Dividing a cow in half does not give you two smaller cows” - Draper L. Kauffman Jr. “Systems one: An introduction to Systems Thinking”.</li>
<li>When we start to think of the system as a process, not a group of components we could say that every company has a Design System.</li>
<li>A Design System is never done but always moving to becoming.</li>
<li>Every organisation has a design system - either it’s delivered or accidental.</li>
<li>“Meta-design is much more difficult than design; it’s easier to draw something than to explain how to draw it” - Donald Knuth.</li>
<li>A Design Language is not about how it communicates with end-users, but the people that use the Design System.</li>
<li>Boundary Objects - people collaborate around objects.</li>
<li>Boundary Objects - need to exist outside your head</li>
</ul>
<p>Types of Boundary Objects:</p>
<ul>
<li>coincidental boundary - maps, shaded work surfaces</li>
<li>repository - code repos, databases</li>
<li>form - data formats, specimen collection sheets</li>
<li>ideal type - design pattern</li>
</ul>
<blockquote>
<p>“Can we make sure a product still feels cohesive and sole, even when many people work on it? Yes, if we have a shared understanding” - Alla Kholmatova</p>
</blockquote>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Patterns Day 2019 - Danielle Huntrods</title>
      <link href="https://www.alwaystwisted.com/articles/patterns-day-2019-danielle-huntrods.html"/>
      <updated>2019-06-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/patterns-day-2019-danielle-huntrods.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="why-design-systems%3F" tabindex="-1">Why Design Systems?</h2>
<p>In their presentation at Patterns Day 2019, <a href="https://twitter.com/dhuntrods">Danielle</a>) talked about the topology of making a successful Design System.</p>
<ul>
<li>most of us are here today as we know, or believe that they help us do better work.</li>
<li>we care about doing better work as they help the outside world in the products that use them.</li>
<li>there is a lot of diversity in what is ‘best practice’ within the Design Systems community.</li>
<li>how do we know what would work for us.</li>
<li>topology.</li>
<li>systems that have worked well could be considered to have a better topology compared to those that have not.</li>
<li>We’re trying to solve problems that no individual can solve alone.</li>
<li>Repeated processes need to be broken down and can aid efficiency.</li>
<li>We have started looking at better ways to deliver projects with things like agile methodology but fundamentally we break things down.</li>
<li>There is much discussion about the naming of things, but not of the interconnectivity of those things which can lead to certain gaps.</li>
<li>unidentified gaps can cause confusion.</li>
<li>overlaps can appear - with duplication of efforts.</li>
<li>bad topology has certain symptoms:
<ul>
<li>duplication of efforts</li>
<li>conflict of ownership</li>
<li>incorrect implementations</li>
<li>recurrent miscommunication</li>
</ul>
</li>
<li>When breaking things down we can lose the overall context.</li>
<li>Breaking things down into components can lose context</li>
<li>Since we cannot anticipate every permutation we need to work on how things go together.</li>
<li>Consistent spacing helps put things back together again.</li>
<li>There can be gaps in skillset, if there are - there will be a struggle in achieving the goals.</li>
<li>There are overlaps in what people want the products to have, marketing want all the scripts, developers do not.</li>
<li>Solutions:
<ul>
<li>keep track of categories.</li>
<li>remember the end goal.</li>
<li>see the negative space.</li>
<li>choose your tools wisely.</li>
<li>establish a single source of truth.</li>
<li>set priorities for when conflict arise.</li>
</ul>
</li>
<li>It’s tempting to fallback on tools, but often it is a people problem. Communication is what can solve most problems.</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Patterns Day 2019 - Amy Hupe</title>
      <link href="https://www.alwaystwisted.com/articles/patterns-day-2019-amy-hupe.html"/>
      <updated>2019-06-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/patterns-day-2019-amy-hupe.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="%E2%80%9Ccontent-is-king%E2%80%9D" tabindex="-1">“Content is King”</h2>
<p>In <a href="http://www.twitter.com/amy_hupe">amy's</a> talk at Patterns Day they discussed the crucial role of content in Design Systems.</p>
<ul>
<li><a href="http://gov.uk/design-system">gov.uk/design-system</a></li>
<li>13 team members working full-time.</li>
<li>Launched June 2018.</li>
</ul>
<h3 id="what-is-content-design%3F" tabindex="-1">What is content design?</h3>
<ul>
<li>content design is more strategic than copywriting</li>
<li>good content design helps people get to what they need as smoothly as possible</li>
<li>It’s based on user needs</li>
<li>“content that’s relevant for the right user at the nighttime in the right channels”</li>
</ul>
<h3 id="content-and-design-systems" tabindex="-1">Content and Design Systems</h3>
<ul>
<li>content in design systems can include
<ul>
<li>the content elements of components, like buttons text or form labels</li>
<li>the documentation of components, the structure of pages</li>
<li>the landing pages</li>
<li>technical documentation, like installation instructions</li>
<li>content best practices, like tone of voice</li>
<li>content about the system - like presentations, blogs, template answers for team members</li>
</ul>
</li>
</ul>
<p>A design system’s content helps people:</p>
<ul>
<li>find it</li>
<li>use it</li>
<li>contribute to it</li>
</ul>
<h3 id="documenting-components-and-patterns" tabindex="-1">Documenting Components and Patterns</h3>
<ul>
<li>Sorting</li>
<li>Naming</li>
<li>Explaining</li>
<li>Justifying</li>
</ul>
<p>As Design System owner and maintainer we are guiding people to use the system in a certain way. Without providing the information to how to use something, it will fail.</p>
<ul>
<li>context is key.</li>
<li>every organisation is different.</li>
<li>you content should be designed to match your organisations goals.</li>
<li>we can’t force people to use a system, so we need to help them choose it. Which starts with good documentation.</li>
<li>we can’t predict the user’s roles or experiences, so you need to be inclusive and include what is relevant.</li>
</ul>
<p>Good documentation can be aided by making it:</p>
<ul>
<li>Clear
<ul>
<li>Naming things help.</li>
<li>Start with a card sort and pattern cut-out session.</li>
<li>But - nobody can agree on anything.</li>
<li>As an industry we cannot all agree on what to name things.</li>
<li>Some people use Brad Frost’s Atomic Design.</li>
<li>Some call things components.</li>
<li>Some call them patterns.</li>
<li>Some call them both.</li>
<li>There is no right way.</li>
<li>User Research can help make the decision on naming.</li>
<li>at GDS components are like objects, so they use nouns.</li>
<li>at GDS patterns are ways of ding things, so they use verbs.</li>
<li>aliasing in the design system search can help people find what they are looking for.</li>
<li>in naming things you will never get consensus, just be consistent.</li>
<li>Consistent</li>
<li>consistency is really important for users to trust a design system</li>
<li>an internal style guide can help people use the correct terms when discussing the design system</li>
<li><a href="http://gov.uk">gov.uk</a> choose to discuss the design system in the third person which helps avoid the us/them potential thinking</li>
<li>Each component has a consistent page structure which helps be predictable, findable and trustworthy.</li>
<li>Using a fixed format helps contributors as well as users of the design system</li>
</ul>
</li>
<li>Useful
<ul>
<li>Good documentation is about writing the right things at the right time for the right reason.</li>
<li>Every line of content in your documentation is one more thing the users will have to do.</li>
<li>Use live examples rather than images - so it’s ‘real’ for people using the design system</li>
<li>Use real content when you can.</li>
<li>Provide examples with code so people can quickly copy and paste into their products to see how it looks</li>
<li>documentation for .<a href="http://gov.uk">gov.uk</a> does 5 jobs at once
<ul>
<li>how it looks</li>
<li>how it behaves</li>
<li>what copy to use</li>
<li>how it’s acessible</li>
<li>code to copy</li>
</ul>
</li>
<li>Honest
<ul>
<li>it’s easy to assume that a design system should provide all the answers.</li>
<li>if there is a gap in the documentation, be open and honest about those gaps.</li>
<li>it is the first steps to filling them.</li>
<li>sharing mistakes and failure should help others avoid them.</li>
<li>Include a ‘known issues and gaps’ for a pattern or component in the documentation.</li>
<li>This could help others contribute fixes, and additional information required to make the components and patterns improve over time.</li>
<li>being honest is not only helpful for the design systems users, but the people actually using the <a href="http://gov.uk">gov.uk</a> sites.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Design Systems impact products and services. Products and service impact people.</p>
<p>Documentation matters - do it right.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Patterns Day 2019 - Alla Kholmatova</title>
      <link href="https://www.alwaystwisted.com/articles/patterns-day-2019-alla-kholmatova.html"/>
      <updated>2019-06-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/patterns-day-2019-alla-kholmatova.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="making-impact-with-design-systems" tabindex="-1">Making Impact With Design Systems</h2>
<p>In their presentation at Patterns Day 2019, <a href="https://www,twitter.com/craftui">Alla</a> discussed getting buy-in for your Design System from teams and leadership.</p>
<h2 id="why-should-our-teams-and-leadership-believe-in-design-systems%3F" tabindex="-1">Why should our teams and leadership believe in Design Systems?</h2>
<ul>
<li>
<p>Revenue</p>
</li>
<li>
<p>Brand and UX improvements</p>
</li>
<li>
<p>Efficiency</p>
<h3 id="revenue" tabindex="-1">Revenue</h3>
<p>Can consistency enabled by a design system, help improve conversions?</p>
<ul>
<li>
<p>2018, Alla managed to test if the consistency of Bulb’s site improved revenue.</p>
</li>
<li>
<p>They had to make sure conversion wasn’t hampered by changes.</p>
</li>
<li>
<p>They didn’t want to skew the results of the joining path by redesigning the sign up path.</p>
</li>
<li>
<p>They used the design system to update colours, and typography.</p>
</li>
<li>
<p>The results was 0.17% in favour of the using the design system.</p>
</li>
<li>
<p>“negligible really”.</p>
<p>Are there other ways to improve revenue?</p>
<ul>
<li>Design Systems can support experimentation and growth.</li>
<li>Mailchimp had a dramatic style change in 2018, base upon the original style guide.</li>
<li>“We parter with Growth to facility experimentation and testing of new patterns” - Alex Lehner, Mailchimp.</li>
<li>At Pinterest, a new element must out perform and existing element to be included.</li>
<li>Pattern experiments are unique to your system.</li>
<li>At <a href="http://Gov.uk">Gov.uk</a> they experimented with the progress indicator, without the indicator they time it took to complete a task didn’t change, so they removed the indicator.</li>
<li>At Habito, they found the form worked better, with a quicker progression with a progress indicator.</li>
<li>A pattern can work differently for different teams and products.</li>
</ul>
<h2 id="ux-and-brand" tabindex="-1">UX and Brand</h2>
<ul>
<li>
<p>Often we talk about how Design Systems make things cohesive.</p>
</li>
<li>
<p>The term cohesive is something Alla hears a lot.</p>
</li>
<li>
<p>“User experience often suffers not because of poor consistency but confusing information architecture and content design.”</p>
</li>
<li>
<p>“Design Systems can help implement and reinforce a visual brand.”</p>
</li>
<li>
<p>GDS is a good example of this. Before the .<a href="http://gov.uk">gov.uk</a> design system, there were 600-700 different UK government websites.</p>
</li>
<li>
<p>“People didn’t really know if they were on an official government website” - Tim Paul.</p>
</li>
<li>
<p>Whatever the reason, there needs to be organisational buy-in.</p>
</li>
<li>
<p>There needs to clarity on what the brand is.</p>
<p>To work out what your brand is, you need clarity. To do this, you can:</p>
<ul>
<li>
<p>purpose and values of the brand Design principles</p>
</li>
<li>
<p>Main screen design using new brand. Brand in context</p>
</li>
<li>
<p>Which then leads to new design patterns and documentation.</p>
<h2 id="efficiency" tabindex="-1">Efficiency</h2>
<ul>
<li>
<p>The top ‘key point’ of selling a Design System.</p>
</li>
<li>
<p>Marvel have a well established Design System</p>
</li>
<li>
<p>“We haven’t used our design system in the last year. We just needed to ship things really fast.” - Yavor Punchev, Marvel App</p>
</li>
<li>
<p>If a point of design systems is efficiency, why did this happen?</p>
</li>
<li>
<p>Work out what you need to invest time in to make things efficient.</p>
</li>
<li>
<p>Investing in form patterns, it allowed Bulb to save 50% of front-end time working on pages that needed forms.</p>
</li>
<li>
<p>FutureLearn, on the other hand, only has one or two forms, so investing the same time on form patterns would not be an efficient use of time.</p>
</li>
<li>
<p>A Design System needs to adopt through it’s product life cycle.</p>
</li>
<li>
<p>Not only looking at the growth and maturity uses.</p>
</li>
<li>
<p>Technology plays a very big part in keeping your Design System efficient</p>
</li>
<li>
<p>“Without React working on the design system alway felt like an uphill struggle.” - Jay Begum, FutureLearn.</p>
<p>Being strategic in what parts you invest in and when can make a really impact on your Design System.</p>
<p>“There needs to be a bigger goal, beyond the design system, for the system to have an impact.” - Alla</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Design Systems and CSS Grid on 24Ways</title>
      <link href="https://www.alwaystwisted.com/articles/design-systems-and-css-grid-on-24ways.html"/>
      <updated>2017-12-13T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/design-systems-and-css-grid-on-24ways.html</id>
      <content type="html">
        <![CDATA[
        <p>This year I have managed to tick one more thing off of my career 'bucket list', I wrote an article for <a href="https://24ways.org/">The Advent Calender for geeks, 24 Ways</a>.</p>
<p>I have been working on a clients design system for the last couple of years and recently we have started on looking at the future of the products it serves. One of the avenues we ventured down has shown us a requirement for some additional patterns for some marketing pages.</p>
<p>This allowed me to finally get to grips (a little) with CSS Grid in the look to phase out our current usage of Susy and replace it with CSS from the grid spec.</p>
<p>The article that I wrote for 24 ways shows my first adventure in putting CSS Grid into the existing design system. I think there's still parts of that article that can be expanded upon, and hope to do so in 2018.</p>
<p><a href="https://24ways.org/2017/design-systems-and-css-grid/">Design Systems and CSS Grid on 24Ways</a></p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>The Design Systems Newsletter</title>
      <link href="https://www.alwaystwisted.com/articles/the-design-systems-newsletter.html"/>
      <updated>2016-08-11T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/the-design-systems-newsletter.html</id>
      <content type="html">
        <![CDATA[
        <p>Let's be honest. <a href="styleguides-pattern-libraries-and-design-languages.html">Styleguides, Pattern Libraries and Design Systems</a> are pretty hot.</p>
<p>For the last 3 years I've been fortunate enough to work on various projects including extending existing pattern libraries, adding to a design system, and creating new pattern libraries and styleguides from (almost) the ground up.</p>
<p>I'm excited by the things I get to create for my clients everyday. I'm excited, seeing what other developers and designers who are also working on design systems, pattern libraries, and styleguides produce, publish and discuss. Every. Day.</p>
<p>Having 'cut my teeth' in curating <a href="http://www.sassnews.com">Sass News</a> before passing on the baton to <a href="http://www.twitter.com/jina">Jina</a>. After a small haitus, I was itching to start sharing what I'm reading again. I setup up a curated account, installed bookmarklets, a (much neccesarty) <a href="http://www.twitter.com/Design__Systems">twitter account</a> and was good to go.</p>
<p>Three issues in and getting close to 650 subscribers, I wanted to write a quick post.</p>
<p>Unlike Sass News where I decied to make it a weekly newsletter, this will be different. There's no real publishing schedule. It's not going to hit your inboxes at 9am(GMT) on Tuesdays...</p>
<p>The Design Systems Newsletter will be sent once I've collated around 7/8 links to artciles, code, frameworks that I feel's worth sharing. This way I won't feel 'pressured' into looking for things and I'll (hopefully) only fill your inboxes with quality content.</p>
<p>If you've not signed up, you can <a href="https://designsystems.curated.co/issues">read the previous emails</a>, and then <a href="https://designsystems.curated.co">subscribe to the newsletter</a>.</p>
<p>As I've mentioned I'm really excited when I see people working on similar problems, codebases, and products and sharing their findings, thougths, and code. If you ever come across something that you think should be featured, don't hesitate to <a href="http://www.twitter.com/StuRobson">let me know</a>.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Better Ghost Button Hover Effect</title>
      <link href="https://www.alwaystwisted.com/articles/a-better-ghost-button-hover-effect.html"/>
      <updated>2016-03-23T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-better-ghost-button-hover-effect.html</id>
      <content type="html">
        <![CDATA[
        <p>I was visiting Clearleft’s <a href="http://www.clearleft.com">website</a> the other day and noticed a <a href="https://uxmag.com/articles/15-ethereal-examples-of-ghost-buttons-in-action">‘ghost button’</a> on the home page that was a little bit, well, off.</p>
<p>Moving my cursor across the screen the button ‘jumped’ when hovering. Only slightly (really) but enough for me to take a dive into Firefox’s developer tools.</p>
<h2 id="using-border" tabindex="-1">Using border</h2>
<p><img src="http://alwaystwisted.com/images/before.gif" alt="image of before" loading="lazy" decoding="async"></p>
<p>In the animated gif above we can see how, when the cursor moves over the button gets a little wider and taller and in doing so makes it look a little ‘off’.</p>
<p>The code used for this effect on the button is something akin to this:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.button-cta</span> <span class="token punctuation">{</span>
  <span class="token property">border</span><span class="token punctuation">:</span> 1px solid #fff<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.button-cta:hover</span> <span class="token punctuation">{</span>
  <span class="token property">border</span><span class="token punctuation">:</span> 2px solid #fff<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This makes the button appear to be 2px wider and 2px taller on hover and means that it ‘moves’ on the page when hovered as it pushed the button down by a pixel and across by a pixel.</p>
<p>I wondered if there was a more pragmatic, progressive fix for this.</p>
<h3 id="making-it-better-box-shadow" tabindex="-1">Making it better box-shadow</h3>
<p>Instead of using an actual border property for the effect I tried using box-shadow. It seems to work pretty well in this case and doesn’t make the button ‘jump’ at all when hovered.</p>
<p><img src="http://alwaystwisted.com/images/after.gif" alt="after" loading="lazy" decoding="async"></p>
<p>In the animated gif above we can see that, now using box-shadow, we get a similar effect but without the button jumping when the cursor hovers over it.</p>
<p>The CSS I added to the button (removing the CSS for the border) was something like this:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.btn-cta</span> <span class="token punctuation">{</span>
  <span class="token property">box-shadow</span><span class="token punctuation">:</span> 0 0 0 1px #fff<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.btn-cta:hover</span> <span class="token punctuation">{</span>
  <span class="token property">box-shadow</span><span class="token punctuation">:</span> 0 0 0 2px #fff<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="in-codepen" tabindex="-1">In CodePen</h3>
<p>Animated images are all well and good and the code examples above don’t really show you <em>too</em> much. So I’ve created <a href="http://codepen.io/sturobson/pen/311483e372532833ce840bc470eb3f0d?editors=1100">a quick CodePen</a> with working examples of a button using border and one using box-shadow.</p>
<p>See the Pen <a href="https://codepen.io/sturobson/pen/311483e372532833ce840bc470eb3f0d/">a better ghose button</a> by Stuart Robson (<a href="https://codepen.io/sturobson">@sturobson</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<h3 id="on-support" tabindex="-1">On Support</h3>
<p>It’s 2016, browser support for box-shadow is pretty good (if you go with global statistics). According to <a href="http://www.caniuse.com">caniuse.com</a> it’s available on <a href="http://caniuse.com/#feat=css-boxshadow">91.33% of browsers being used daily</a>. That other ~8 percent though. IE8 and Opera mini (5–8), let’s not forget those. We need to look at doing something <a href="http://dowebsitesneedtolookexactlythesameineverybrowser.com/">similar</a>.</p>
<h4 id="ie8-fallback" tabindex="-1">IE8 Fallback</h4>
<p>For IE8 we can use a <a href="https://css-tricks.com/how-to-create-an-ie-only-stylesheet/">conditional comment</a> to target that browser by having a HTML class available. We could perhaps keep the border or we could remove the border and add text-decoration on hover, something like:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.lt-ie8 .btn-cta</span> <span class="token punctuation">{</span>
  <span class="token property">border</span><span class="token punctuation">:</span> 1px solid #fff<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.lt-ie8 .btn-cta</span> <span class="token punctuation">{</span>
  <span class="token property">text-decoration</span><span class="token punctuation">:</span> underline<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h4 id="opera-mini" tabindex="-1">Opera mini</h4>
<p>Instead of creating a fallback, let’s look at making something progressively enhanced. Let’s first off add some JavaScript that will test if the browser supports box-shadow:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">if</span> <span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'detect'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>style<span class="token punctuation">.</span>boxShadow <span class="token operator">===</span> <span class="token string">''</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">'html'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>className <span class="token operator">+=</span> <span class="token string">' boxshadow'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Now we can write some CSS that will work giving Old IE, Opera Mini and the original border effect and if the browser does have box-shadow and JavaScript doesn’t fail to load we get the nicer effect using box-shadow:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.btn-cta</span> <span class="token punctuation">{</span>
  <span class="token property">border</span><span class="token punctuation">:</span> 1px solid currentColor<span class="token punctuation">;</span>
  <span class="token property">box-shadow</span><span class="token punctuation">:</span> 0 0 0 1px currentColor<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.btn-cta:hover</span> <span class="token punctuation">{</span>
  <span class="token property">border</span><span class="token punctuation">:</span> 2px solid currentColor<span class="token punctuation">;</span>
  <span class="token property">box-shadow</span><span class="token punctuation">:</span> 0 0 0 2px currentColor<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.boxshadow .btn-cta</span> <span class="token punctuation">{</span>
  <span class="token property">border</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.boxshadow .btn-cta:hover</span> <span class="token punctuation">{</span>
  <span class="token property">border</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="over-engineering" tabindex="-1">Over Engineering</h3>
<p>Is this solution too much? I guess when you look at supporting as many browsers as you possibly can, then maybe it looks that way. Perhaps you could forgo the support for Opera Mini (5–8) as the button will still have the whitespace around it to make it look not like a paragraph of text. You could change how you create the 'button'. Perhaps only add a style reset for anything with box-shadow and leave OldIE and older Opera mini browsers with a default button style. Whatever's fit for yours and your users needs. Personally I’d be happy to add a couple more lines of CSS for this so that it can work for as many browsers as possible.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Determining CSS Units For Your Pattern Library</title>
      <link href="https://www.alwaystwisted.com/articles/determining-css-units-for-your-pattern-library.html"/>
      <updated>2016-03-21T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/determining-css-units-for-your-pattern-library.html</id>
      <content type="html">
        <![CDATA[
        <p>For some time now I’ve been working on an inherited codebase, moving it from it’s original single purpose of being a website to a cohesive design language with a pattern library and front-end framework.</p>
<p>One part of doing this is looking at the existing code to see if it’s possible to improve it and, as one of our underlying goals, make it easier to understand and more ‘human-readable’.</p>
<p>In doing that we’ve uncovered a few things that could be improved and more consistent. One of those things is how CSS units are being used.</p>
<h2 id="types-of-units" tabindex="-1">Types Of Units</h2>
<p>There are <a href="https://css-tricks.com/the-lengths-of-css/">quite a few lengths of CSS</a> available and looking at the existing CSS (that currently uses Sass) we have found these 5 being used:</p>
<ul>
<li>em</li>
<li>rem</li>
<li>px</li>
<li>%</li>
<li>vh</li>
</ul>
<p>The majority of the time a <code>rem</code> is in use with a <code>px</code> fallback for Old IE. This is using a Sass mixin to create the <code>rem</code> value from the <code>px</code> value variable used in the mixin.</p>
<p>All of the units are found in use for fonts, margins, paddings, borders, widths, heights, line-heights and media queries. Along with things like box-shadow and text-shadow.</p>
<p>As we are trying to make the CSS used within the pattern library easier to read and understand I’m now looking at ‘guidelines’ as to what CSS unit should be used where.</p>
<h2 id="categorising-css-unit-usage" tabindex="-1">Categorising CSS Unit Usage</h2>
<p>So far I’ve got this:</p>
<h3 id="ems" tabindex="-1">ems</h3>
<p>The <code>em</code> unit is only to be used within media queries. Currently most media queries are created using a Sass mixin and variable or value to define the min-width.</p>
<h3 id="px" tabindex="-1">px</h3>
<p>I think we must restrict the use of <code>px</code> to box-shadow, text-shadow, border and height. Anything that could look a little bit silly when you zoom on a desktop browsers.</p>
<h3 id="rem" tabindex="-1">rem</h3>
<p>Any font-size or vertical spacing should use the <code>rem</code> unit. To have consistent rhythm if the browser is resized or in between media queries.</p>
<h3 id="%25" tabindex="-1">%</h3>
<p>Percentages should be used only for all things horizontal. Widths, left and right margins or padding.</p>
<h3 id="unitless" tabindex="-1">unitless</h3>
<p>We should not use any CSS unit when <a href="http://meyerweb.com/eric/thoughts/2006/02/08/unitless-line-heights/">defining our line-height</a>.</p>
<h3 id="vh" tabindex="-1">vh</h3>
<p>A ‘special’. The <code>vh</code> unit is currently only used on one aspect of the homepage.</p>
<h2 id="moving-forward" tabindex="-1">Moving forward</h2>
<p>In defining new guidelines and implementing them on a codebase it can create better consistency within the pattern library and overall design language. This will help the maintainability, the usage and the development of the codebase.</p>
<p>Although deciding upon, defining and sticking to guidelines for such a marginal part of the codebase could seem a little over-engineered there are several improvements of this ‘size’ in the works which should lead to a better, more consistent design system which I hope will empower other teams to start using it on their projects.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Web Developers New Working Week</title>
      <link href="https://www.alwaystwisted.com/articles/a-web-developers-new-working-week.html"/>
      <updated>2016-03-14T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-web-developers-new-working-week.html</id>
      <content type="html">
        <![CDATA[
        <p>Why spend the week in your comfort zone, working on the same browser under the same conditions you’re used to. Let’s switch it up a bit.</p>
<h3 id="tap-tap-monday%3A" tabindex="-1">Tap Tap Monday:</h3>
<p>Monday’s is the day to unplug your mouse and test your work using only the keyboard for navigating the site you’re working on.</p>
<h3 id="grayscale-tuesday" tabindex="-1">Grayscale Tuesday</h3>
<p>Tuesday is the day to test your work for various forms of colour blindness.</p>
<p><a href="https://chrome.google.com/webstore/detail/spectrum/ofclemegkcmilinpcimpjkfhjfgmhieb?hl=en">Spectrum - a Chrome extension</a></p>
<p><a href="https://addons.mozilla.org/en-GB/firefox/addon/colorblind-design/">Colorblind Design - a Firefox extension</a></p>
<h3 id="different-browser-wednesday" tabindex="-1">Different Browser Wednesday</h3>
<p>Wednesday’s… If you’re used to developing for most of your day in <a href="https://www.mozilla.org/en-GB/firefox/new/">Firefox</a>, try <a href="https://www.google.com/chrome/">Chrome</a>, if you’re using <a href="https://www.microsoft.com/en-gb/windows/microsoft-edge">Edge</a> try <a href="http://www.opera.com/">Opera</a>. Today’s the day to break out into a different browser for the day to develop in.</p>
<h3 id="throttle-thursday" tabindex="-1">Throttle Thursday</h3>
<p>Thursday is the <a href="http://fourkitchens.com/blog/article/throttled-thursdays">day to throttle your connection</a>. There’s a whole host of ways to do this (most of which are <a href="http://fourkitchens.com/blog/article/throttled-thursdays">shown in this blogpost</a>) my personal favourite is <a href="http://slowyapp.com/">Slowy</a>.</p>
<h3 id="friday" tabindex="-1">Friday</h3>
<p>It’s Friday. The working week is nearly over. Enjoy the day in the comfort of your own browser and don’t forget the #deskbeer at 4pm.</p>
<p>Although this post is 'a bit of fun'. There's some sense in testing for various scenarios. I've not even mentioned 'turn JavaScript off for the weekend', you can decide to do that yourself.</p>
<p>I don’t care if Monday’s blue, Tuesday’s grey and Wednesday too. Thursday I don’t care about you. It’s Friday I’m in love.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Using Lists In A Yeoman Generator</title>
      <link href="https://www.alwaystwisted.com/articles/using-lists-in-a-yeoman-generator.html"/>
      <updated>2016-01-22T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/using-lists-in-a-yeoman-generator.html</id>
      <content type="html">
        <![CDATA[
        <p>For a large project I’ve been working on with Monotype I recently, through some requirement changes, needed to create a list of options in <a href="http://yeoman.io/">Yeoman Generator</a>. After some quick googling I found that the best option for me was to use the list type available.</p>
<p>Further reading various Stack Overflow questions and answers, examples from the <a href="https://github.com/SBoudrias/Inquirer.js">inquirer.js repo</a> and any documentation I was a little flummoxed.</p>
<p>Every example I could find gave simple one-word options. This works when choosing what size of pizza you require:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">var</span> prompts <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'list'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'features'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">message</span><span class="token operator">:</span> <span class="token string">'What do you want to make today?'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">choices</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'Jumbo'</span><span class="token punctuation">,</span> <span class="token string">'Large'</span><span class="token punctuation">,</span> <span class="token string">'Standard'</span><span class="token punctuation">,</span> <span class="token string">'Medium'</span><span class="token punctuation">,</span> <span class="token string">'Small'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>

<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">prompt</span><span class="token punctuation">(</span>
  prompts<span class="token punctuation">,</span>
  <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// do things with the answer here</span>
  <span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>For this project I needed a more descriptive explanation of what they were about to install. Was it a project for a new typeface specimen? A new email project? A quick prototype? We needed to be able to be verbose with out list of choices.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">var</span> prompts <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>
<span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'list'</span><span class="token punctuation">,</span>
<span class="token literal-property property">name</span><span class="token operator">:</span> ‘project’<span class="token punctuation">,</span>
<span class="token literal-property property">message</span><span class="token operator">:</span> <span class="token string">'What type of project do you want to create today?'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">choices</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        “a <span class="token keyword">new</span> <span class="token class-name">email</span> campaign“<span class="token punctuation">,</span>
        “a low fidelity prototype“<span class="token punctuation">,</span>
        “a <span class="token keyword">new</span> <span class="token class-name">typeface</span> specimen“<span class="token punctuation">,</span>
        “a <span class="token keyword">new</span> <span class="token class-name">landing</span> page“<span class="token punctuation">,</span>
        “a <span class="token keyword">new</span> <span class="token class-name">bespoke</span> article”
    <span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">prompt</span><span class="token punctuation">(</span>prompts<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// do things with the answer here</span>
<span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Looking at this and how the simpler example had one-word answers I thought this would be a problem when it came to assigning the choice made to various options that may or may be required.</p>
<p>I searched the documentation, various blogposts and Stack Overflow (again) for an answer and then I tried something.</p>
<p>Taking a look at the <a href="https://github.com/yeoman/generator-gulp-webapp">gulp web app generator</a> from the Yeoman Github organisation I looked at how they had used the checkbox type from inquirer.js –</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">var</span> prompts <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>
  <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'checkbox'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'features'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">message</span><span class="token operator">:</span> <span class="token string">'What more would you like?'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">choices</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'Sass'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">value</span><span class="token operator">:</span> <span class="token string">'includeSass'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">checked</span><span class="token operator">:</span> <span class="token boolean">true</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'Bootstrap'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">value</span><span class="token operator">:</span> <span class="token string">'includeBootstrap'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">checked</span><span class="token operator">:</span> <span class="token boolean">true</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'Modernizr'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">value</span><span class="token operator">:</span> <span class="token string">'includeModernizr'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">checked</span><span class="token operator">:</span> <span class="token boolean">true</span>
  <span class="token punctuation">}</span><span class="token punctuation">]</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
    <span class="token comment">//</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">;</span></code></pre>
<p>Here we had name, value and checked. Well I knew I didn’t need checked so I tried using name and value. It worked.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">var</span> prompts <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'list'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'features'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">message</span><span class="token operator">:</span> <span class="token string">'What do you want to make today?'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">choices</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token punctuation">{</span>
        <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'a new email campaign'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">value</span><span class="token operator">:</span> <span class="token string">'includeEmail'</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span>
        <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'a low fidelity prototype'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">value</span><span class="token operator">:</span> <span class="token string">'includePrototype'</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span>
        <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'a new typeface specimen'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">value</span><span class="token operator">:</span> <span class="token string">'includeSpecimen'</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token comment">//</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span></code></pre>
<p>Now, using <code>name</code> we can have a verbose, descriptive option and use it’s <code>value</code> when generating a new project to include the relevant files, bits of HTML or CSS, images, fonts etc.</p>
<p>So now, when we are in a terminal window and <code>Yo</code> the generator we get a nice list to choose one option from.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Styleguides, Pattern Libraries and Design Languages</title>
      <link href="https://www.alwaystwisted.com/articles/styleguides-pattern-libraries-and-design-languages.html"/>
      <updated>2016-01-20T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/styleguides-pattern-libraries-and-design-languages.html</id>
      <content type="html">
        <![CDATA[
        <p>The terminology surrounding front-end ’styleguides’ seems to be ever expanding. We have styleguides, pattern libraries, UI libraries, design systems, design patterns and a design language to name a few.</p>
<p>Some of these are similar to each other, some are used to encompass everything. For clarity it’s best to define what you are meaning when using one of these terms. It will help you and your colleagues understand what part of the project you are talking about without possible confusion.</p>
<p>This is how I see three of the often used terms. Style guides, Pattern Libraries and Design Languages.</p>
<h2 id="the-what%2C-the-where%2C-the-how-and-the-why." tabindex="-1">The what, the where, the how and the why.</h2>
<h3 id="pattern-libraries" tabindex="-1">Pattern Libraries</h3>
<p>A pattern library is a collection of front-end code that creates a component part of the overall design of the page. It is ‘the what’ of the website. If you need to use a carousel this is ‘what’ code you would use.</p>
<h3 id="styleguides" tabindex="-1">Styleguides</h3>
<p>With a pattern library being ‘the what’ of a sites design a styleguide is ‘the how’ and ‘the where’. You have this collection of colours and typefaces and the styleguide will show you how and where to put them in your website. The patterns you need for a project will have their placement and usage defined within the styleguide.</p>
<p>It is ‘a guide’ though. It should allow for deviation where necessary or chosen when content dictates a change in the design.</p>
<h3 id="design-language" tabindex="-1">Design Language</h3>
<p>As we have ‘the what’, ‘the where’ and ‘the how’ then a Design Language, in part, is the overall ‘the why’. With our ready–made patterns and our styleguide showing us where and how to use them the Design Language will instruct us as to why we would use ‘the what’ and’(the) where’ we should put them altogether.</p>
<h2 id="the-simplest-of-terms" tabindex="-1">The simplest of terms</h2>
<p>That’s how I see these three terms, like a ‘Johnny Ball Reveals All’ trio for projects.</p>
<p>Out of the three I think I’ve not given the Design Language as much credit as to what it is. It can be seen as much more than the simple why you would put what where and how. It should be the living, growing ‘thing’ for the project, in all aspects of design, not just of the web. From my point of view, as a front-end developer, that’s for others to define and express better that I could try to.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Getting Buy In For Your Styleguide</title>
      <link href="https://www.alwaystwisted.com/articles/getting-buy-in-for-your-styleguide.html"/>
      <updated>2016-01-18T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/getting-buy-in-for-your-styleguide.html</id>
      <content type="html">
        <![CDATA[
        <blockquote>
<p>“If you book them, they will come.”</p>
<p>(not) Jim Morrison</p>
</blockquote>
<p>In creating a front-end styleguide, design language and framework for (initially) a small part of a company, getting ‘buy in’ from other departments and developers could be a potential problem.</p>
<p>Here’s this collection of files you’ve created that help you with your day–to–day work with a pattern library of your website, but how can that possibly help another department, or even another company within a larger organisation.</p>
<p>Part of it comes down to how you have gone about creating your design language, your pattern library and your front-end framework. Part of it is how you go about evangelising what you’ve created.</p>
<p>A style guide, built upon a pattern library that is part of the design language is just that. A guide (more on this, in another article (to be written)). It is not ‘the law’, it should have the ability to be wielded masterfully by another designer, to be modified, adapted, re-written (in parts) to suit the sites design and requirements.</p>
<p>In an organisation with many teams potentially creating sites that could be poles apart from each other a clear front-end architecture of possibilities with a component–based, modular pattern library can be of great benefit to all.</p>
<p>You should bestow the virtues of using your front-end framework and pattern library, showing how that, if every developer started using it, it would improve not only itself but the websites that are the customer / visitor / user facing.</p>
<p>The ‘thing’ (the front-end framework and pattern library) can be improved, by everyone, be it someone who’s part of the ‘original team’ or another developer working for another company or part of the organisation.</p>
<p>Using version control and creating a system of how to update the codebase, maybe with peer review, means everyone in the organisation can have their say, giving their opinion on edits to the code all the while helping the overall ‘thing’ and a sites visitor.</p>
<p>If everyone within a large organisation uses the same front-end framework and architecture it allows for an increasing improvement in code quality, bringing new and/or better design patterns, performance improvements all leading to ‘better’ sites (from a code perspective) for everyone.</p>
<p>This can be of benefit, not only to someone visiting the site with a more performant faster page and better accessibility, for example, but also to the organisation as a whole.</p>
<p>If every developer on every project starts to use the same front-framework, the same pattern library it can make it easier for developer to switch teams, or ‘jump in’ as an extra pair of hands. Using the same base elements of the front-end architecture means the developer will be ‘up to speed’ in no time. That’s got to be a good thing.</p>
<p>I think there are many benefits for a company to treat their front-end framework and pattern library as a going concern, there is always room from improvement, the work is never ‘done’.</p>
<blockquote>
<p>“No matter how good you get you can always get better, and that’s the exciting part.”</p>
<p>Tiger Woods</p>
</blockquote>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Deleting Git Tags Locally and on Github</title>
      <link href="https://www.alwaystwisted.com/articles/deleting-git-tags-locally-and-on-github.html"/>
      <updated>2015-06-08T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/deleting-git-tags-locally-and-on-github.html</id>
      <content type="html">
        <![CDATA[
        <p>So, I’m currently in the depths of helping a client with getting the front-end of their design language off the ground and also a neat little Yeoman generator to allow anyone working for them to quickly spin up some basic HTML and use the design language.</p>
<p>Git tags can be used to specify points in the history of a project as something important. Usually these are used to mark releases(v0.0.01, and so on). I’m using tags in these projects so that my client can easily update their copy of the Yeoman generator on their machine when a new feature or bugfix has been implemented.</p>
<p>The design language is making use of <a href="http://www.bower.io">Bower</a> so that it gets pulled in (or not) nice and simple into the Yeoman framework that’s being created.</p>
<p>Using both Bower and Yeoman has required me tagging some commits to the repo with a version number.</p>
<p>At some point, probably a Friday, I was getting annoyed with the version numbers I was using expotentially on something that wasn’t near completion. I decided to nuke all the git tags both locally and remotely so that I could (cheekily) start again.</p>
<h3 id="delete-all-git-tags-locally" tabindex="-1">Delete all Git tags locally</h3>
<p>To delete all the git tags locally I happened upon this line of code to enter into the command line. This wil irrecoverably remove any and all of the git tags within the folder you enter the code in terminal.</p>
<p>git tag -d <code>git tag | grep -E '.'</code></p>
<h3 id="delete-all-tags-in-a-remote-repo" tabindex="-1">Delete all tags in a remote repo</h3>
<p>Finally to delete all of the tags in the remote repo also I found this line of code that did the job. This wil irrecoverably remove any and all of the git tags from the attached remote server of the folder you enter the code in terminal.</p>
<p>git ls-remote --tags origin | awk '/^(.<em>)(s+)(.</em>[a-zA-Z0-9])$/ {print ':' $2}' | xargs git push origin</p>
<p>Some pretty horrendous and scary looking regex’d git codings but it worked perfectly.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Jump Start Sass</title>
      <link href="https://www.alwaystwisted.com/articles/jump-start-sass.html"/>
      <updated>2015-06-03T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/jump-start-sass.html</id>
      <content type="html">
        <![CDATA[
        <p>UPDATE: I'm no longer writing this.</p>
<p>So, I'm co-writing a <a href="https://learnable.com/books/jump-start-sass">book</a>. On <a href="http://www.sass-lang.com">Sass</a>. With <a href="http://www.twitter.com/hugogiraduel">Hugo</a>. For <a href="http://www.sitepoint.com/">SitePoint</a>.</p>
<p>It will introduce preprocessors, the basic tenets of Sass, project architecture and the ecosystem surrounding the language.</p>
<p>I'm really excited, not only do I get to work with Hugo, we are also lucky to have the awesome <a href="http://www.twitter.com/kaelig">Kaelig</a> as our technical editor.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A New Workshop at WebDevConf</title>
      <link href="https://www.alwaystwisted.com/articles/a-new-workshop-at-webdevconf.html"/>
      <updated>2015-06-02T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-new-workshop-at-webdevconf.html</id>
      <content type="html">
        <![CDATA[
        <p>I'm really happy to announce, after the success of last years workshops, that I'll be presenting a new workshop on 'Getting Super Powers with Sass' at this years WebDevConf in Bristol.</p>
<h3 id="getting-super-powers-with-sass" tabindex="-1">Getting Super Powers with Sass</h3>
<p>So, you’re comfortable with CSS but you really want to jump into a telephone box and fly away with Sass as your new super power. Getting Super Powers with Sass will show you the basics of the programming language before flying into practical and pragmatic uses to make creating CSS as easy as putting on your cape.</p>
<p>The workshop will teach</p>
<ul>
<li>The Sass basics of nesting, variables, mixins, extends, placeholders and functions.</li>
<li>How to decide upon an ideal file and folder architecture.</li>
<li>Creating mixins for common snippets of CSS.</li>
<li>How to write and maintain variables for a project.</li>
<li>Where to ‘stop’ when using Sass in your code.</li>
<li>Where Sass fits within a modern front-end architecture, looking at Gulp and Grunt.</li>
</ul>
<p>The workshop will be have aspects where you will need to use a laptop, this ideally will also need Sass installed.</p>
<h3 id="about-the-event" tabindex="-1">About the event</h3>
<p>WDC (webdevconf) is a one day conference held in Bristol each year, with a day of workshops held beforehand. My workshop (Getting Super Powers with Sass) will run on Thursday 8th October 2015 in the afternoon.</p>
<p><a href="http://2015.webdevconf.com/workshops">More information available here.</a></p>
<h3 id="testimonials" tabindex="-1">Testimonials</h3>
<p>Here are a few testimonials from previous workshop attendees.</p>
<blockquote>
<p>“An amiable, engaging and extremely useful run through Sass from top to bottom. Stu concisely covered the basics, followed up with some nifty advanced techniques and wrapped up the day with a Q&amp;A on structuring Sass projects.”</p>
<p>Dan Dineen - <a href="http://www.bath.ac.uk/">University of Bath</a></p>
</blockquote>
<blockquote>
<p>“Stu did a fantastic job making Sass accessible to beginners. The workshop was incredibly practical, light on preaching and heavy on pragmatism. Even an old dog like me, came away wanting to give Sass another go. Highly recommended!”</p>
<p>Alex Morris - <a href="http://www.adobe.com/">Adobe</a></p>
</blockquote>
<blockquote>
<p>“The workshop was well balanced, Stuart shared examples and got us using Sass within minutes of the workshop starting, it was a practical hands-on introduction from a clear expert. The relaxed &amp; informal setting made it a pleasure to attend. ”</p>
<p>Steve Kirkley - <a href="http://www.twitter.com/stevekirtley">@stevekirtley</a></p>
</blockquote>
<blockquote>
<p>“Stu’s knowledge of Sass and his way of explaining the ins and outs, for me, are unparalleled to anyone else I know.  Highly recommended if you are new to Sass, or are interested in increasing your understanding of this wonderful language.”</p>
<p>Nick Toye - <a href="http://www.nicktoye.co.uk/">Pixels &amp; Code</a></p>
</blockquote>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Workflows and Tooling</title>
      <link href="https://www.alwaystwisted.com/articles/workflows-and-tooling.html"/>
      <updated>2015-05-20T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/workflows-and-tooling.html</id>
      <content type="html">
        <![CDATA[
        <p>Before I decided to venture out and become a full-time front-end developer my day job was quite different. I worked for a conference set and stage design company. I didn’t design the sets. I was in the warehouse making up the stock we had to fit the design in both size and colour variations.</p>
<p>The company had a large stock of ‘flats’ ready to be covered in a felt, pvc or kiss laminate of the clients choosing. It was a case of getting the flats required, cutting the fabric and bubble wrap for protection and then some stapling and tapin up ready for transport.</p>
<p>The company is about 18 years old now. When I left in 2012 there were a couple of flats that were as old as the company. From the first contract it got. If you look at those flats you can see the progression in tooling and workflow from those small beginnings to how the company works today.</p>
<p>So, let’s take a basic 8 foot by 4 foot flat. The face is a 5mm sheet of plywood which is glued and stapled on to a backing frame of 2 inch by 1 inch timbre. This makes the flat 8 foot by 4 foot by (about) 2 inches.</p>
<p>To cover a flat in fabric you would need to wrap your chosen fabric around so that the face and all sides are covered leaving the back sparse and bare (as the audience won’t be seeing that bit).</p>
<p>Going back to the these ‘antique’ flats that were kicking about. They were 8 foot by 4 foot. If you looked at the back you could see:</p>
<ul>
<li>that when the company first started the fabric was stapled onto inside of the 2x1 timber. You can still see the staples from a hand stapler that tacked the fabric on</li>
<li>a second look reveals the time when the company invested in air tools and the hand stapler was replaced with an air gun that easily sped up production.</li>
<li>a third look shows that the fabric is now stapled onto the edge of the 2x1 timber saving time because it’s easier and just as effective but also allows creation of larger panels because the fabric has a little more play to stretch.</li>
</ul>
<p>So, over the lifetime of the company, so far, they developed and adapted their workflow and tooling to help speed things up and create more possibilities. This in turn led to reduced company costs which were passed onto the clients and the profit margin.</p>
<p>Moving from a hand stapler which you have (pretty much) full control of to an air gun that’s pushing out staples with 100psi of pressure would be pretty daunting. You lose a bit of ‘the feel’ of control and if not used wisely you could end up stapling your thumb (which I did more than once).</p>
<p>When looking at modern workflows and tooling presented to us in web development it’s easy to quickly cast aspersions on things as we give a little bit of control away.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Updating Dependencies in a package.json</title>
      <link href="https://www.alwaystwisted.com/articles/updating-dependencies-in-a-packagejson.html"/>
      <updated>2015-05-18T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/updating-dependencies-in-a-packagejson.html</id>
      <content type="html">
        <![CDATA[
        <p>I am currently working for a client helping to build out a front-end framework, design pattern library for them to use throughout their company, for both internal teams and developers as well as external agencies and freelancers (like myself). A project that can will allow for simple prototyping, making a marketing site and beyond.</p>
<p>Together we have been reiterating the requirements of what is needed and have added and removed things as necessary. The whole package will be distributed using Yeoman. We picked the “web’s scaffolding tool” because of the various parts of the codebase that may or may not be required for any project it might get used on.</p>
<p>To start, I picked out the preexisting gulp webapp Yeoman generator to work on and adapt as needed. From the off this is fantastic as it allows a quick setup and creation of a project folder but the way the gulpfile.js is written does not and will not suit the needs of the entire project going forward.</p>
<p>As this was decided I made a start hacking together a gulpfile.js that would work for the project goals. This was by taking bits of the existing JavaScript, borrowing bits from another gulp-based boilerplate I have been using and adding new code and plugins as required.</p>
<p>Doing this leaves the package.json file in a bit of a mess. Borrowing from here and there I could not be sure if I was up-to-date on all the packages I included.</p>
<p>I wanted a way to update all of the dependencies in a quick and painless manner.</p>
<h2 id="updating-%E2%80%98all-the-things%E2%80%99" tabindex="-1">Updating ‘all the things’</h2>
<p>After typing various combinations of words into a search engine. I clicked on a result that took me to <a href="http://npmjs.com/package/npm-check-updates">npm-check-updates</a>. This Node module when invoked on the command line will run through your package.json file, check to see if each dependency is the latest and, depending on what else you give in the command, replace the dependency version number with the latest.</p>
<p>To install the Node module you enter the following code into your terminal and let it fly off and install itself globally.</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> npm-check-updates <span class="token parameter variable">-g</span></code></pre>
<p>After this is installed you would need to <code>cd</code> into the relevant project folder. If you then type:</p>
<pre class="language-bash"><code class="language-bash">npm-check-updates</code></pre>
<p>You will be presented with what packages you have and then if there is an update for each one.</p>
<p>To update all of the dependencies within that package.json you would enter:</p>
<pre class="language-bash"><code class="language-bash">npm-check-updates <span class="token parameter variable">-u</span></code></pre>
<p>To only see if certain dependencies are out-dated (for example, gulp-sass) and have newer versions you would use something like:</p>
<pre class="language-bash"><code class="language-bash">npm-check-updates <span class="token parameter variable">-f</span> gulp-sass</code></pre>
<p>So, this is great. The Node module helps me quickly check to see if the dependencies are up-to-date and (if I choose to) update them (all) if required.</p>
<p>This is only half way there though. I have already got a folder of Node modules. So I need to override what is there already now that I have an updated package.json.</p>
<h2 id="back-to-day-0" tabindex="-1">Back to day 0</h2>
<p>I decided the easiest way to do this was to delete the folder completely and re-install the dependencies. As we are in terminal, we can do it all from the command line too. Making sure we are in the correct project folder we would simply write:</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">rm</span> <span class="token parameter variable">-fr</span> node_modules</code></pre>
<p>Which would make sure (-f, force) we remove all of the files and folders (-r, recursively) in one go (-fr). After that has happened we will then need to re-install all of the depenencies again:</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span></code></pre>
<p>Now we have got a an up-to-date project, using the latest (chosen) gulp dependencies for our awesome website making. Automating this as much as possible to a few lines of code for the command line helps speed up and maintain a working project. There should, of course, be a slight note of caution. Running npm-check-updates -u whilst quickly updating all the dependencies within your package.json could by doing so break things where and updated dependency has changed.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>The Conference Audience</title>
      <link href="https://www.alwaystwisted.com/articles/the-conference-audience.html"/>
      <updated>2015-03-11T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/the-conference-audience.html</id>
      <content type="html">
        <![CDATA[
        <blockquote>
<p>“If you’ve not got anything nice to say, then don’t say anything at all”</p>
</blockquote>
<p>A phrase I’m sure many people could say they’ve heard from a parental voice at a young age. I’m sure it was possibly something Basil Fawlty would’ve said during “The Kipper And The Corpse” too.</p>
<p>In 2014, I was overjoyed to have been able to speak at various meetups and some conferences too.</p>
<p>Unbeknownst to anyone that follows me on the twitters but hasn’t spent time with me in real life. I can am not really the ‘social butterfly’ I am when sending a beautifully crafted subtweet behind a 13' Retina MacBook screen.</p>
<p>I’m quite the introvert, I can spend most of the working day without any conversation. I don’t mind that. Part of the reason I wanted to talk was to try and ‘break out’ of being a shell of my online self. I used to play guitar in a band when I was growing up. I played ‘lead’ but I didn’t have the persona of a lead guitarist. Often at gigs I’d have my back to the audience. Only listening to my guitar and the snare drum through an monitoring system that was available. To be honest. I’m not a fan of being ‘in the limelight’ in reality. The barrier of a screen helps me be someone a little different.</p>
<p>So, to try and ‘break out’ I decided to put in talk proposals, ask to speak at a few meetups and I was fortunate to be asked to speak (at the first online Sass Summit) too.</p>
<p>I don’t think I want to doing any public speaking anymore. In part, I guess you could say unfortunately, this is due to some criticism from audience members at the last couple of talks I gave. I know words shouldn’t hurt but they easily do when you’re miles from home and family and extremely tired too.</p>
<p>I was ‘accused’ (a strong word, my choice) of falling asleep during a talk I was giving. That hurt, I was tired. Tired with nerves and lack of sleep. At a different event I dissapointed a member of the audience due to my ‘lack of profresionality’ because I needed to refer to some notes on a brand new talk I was giving. I thought it’d be better for me to have some form of script than try and unprofessionally ‘wing it’.</p>
<p>The other reason is that I know developers far better than me that should be talking. I’m happy to listen. I’ve set up <a href="http://www.twitter.com/LDN_Sass">LDN Sass</a> so I can listen.</p>
<p>Going back to the quote at the start of this post, and echoing Alice Bartlett’s recent post on what makes <a href="http://alicebartlett.co.uk/blog/audiencehood">a good audience member</a>.</p>
<blockquote>
<p>“…if you’re going to hop on twitter and criticise a talk, make it constructive, and if you have nothing constructive to say, then shut up.”</p>
</blockquote>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Updating My Sass Media Query Mixin</title>
      <link href="https://www.alwaystwisted.com/articles/updating-my-sass-media-query-mixin.html"/>
      <updated>2015-03-09T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/updating-my-sass-media-query-mixin.html</id>
      <content type="html">
        <![CDATA[
        <p>Back in April 2013, I wrote about my <a href="../post.php%EF%B9%96s=2013-04-01-my-media-query-mixin.html">media query mixin</a> and how I wanted to keep it simple yet adaptable to most of my needs.</p>
<p>I wanted it so that I can change from min-width to max-width easily, to also use height, to make sure it’s computed in ems and not be tied down to any variables. The last one still holds true. I believe we should be still adopting the <a href="http://www.twitter.com/stephenhay">Stephen Hay</a> approach I <a href="../post.php%EF%B9%96s=2012-04-28-a-common-set-of-breakpoints-to-start.html">mentioned in 2012</a>:</p>
<blockquote>
<p>“Start with the small screen first, then expand until it looks like shit. Time to insert a breakpoint!”</p>
</blockquote>
<h2 id="moving-forward" tabindex="-1">Moving forward</h2>
<p>Since September (2014) I’ve been lucky enough to hold the role as an editor for SitePoint. Specifically their Sass channel. One of the great pleasures of doing this is reading other peoples articles on Sass and learning new things. It’s great.</p>
<p>Recently <a href="http://hugogiraudel.com/">Hugo</a> (you know him? He writes <a href="https://github.com/HugoGiraudel/awesome-sass">quite a bit</a> about Sass) <a href="http://www.sitepoint.com/breakpoints-tweakpoints-sass/">wrote an article</a> about using breakpoints and <a href="https://adactio.com/journal/6044">tweakpoints</a> in Sass which I really enjoyed reading and editing.</p>
<p>I’ve wanted to adapt the media query mixin he created to include my own ‘needs’ since and have managed to squeeze some time out of the day to create it.</p>
<h2 id="mash-it-up" tabindex="-1">Mash it up</h2>
<p>Essentially it’s a ‘mash-up’ of both mixins. It takes what is the media query I’ve been using for two years as it’s inner workings:</p>
<p>@mixin mq($point, $IE9: false, $query1: min, $query2: width) {
@if $IE9 == true{
.lt-ie9 &amp; {
@content;
}
}
@media (#{$query1}-#{$query2}: $point / $doc-font-size +em) {
@content;
}
}</p>
<p>From Hugo’s new tweakpoints and breakpoints media query it’s using the <code>@if</code> and <code>@else if</code> statements. It’s a little more verbose as a mixin and now requires me to possibly have global variables for breakpoints but it also allows me to have granular, component based tweakpoints as <a href="rethinking-your-sass-variables.html">I discussed in a recent article</a>.</p>
<p>My new Sass media query mixin now looks like this:</p>
<p>@mixin sassifaction-mq($point, $query1: min, $query2: width, $ie: false) {
@if map-has-key($tweakpoints, $point) {
@if $ie == true{
.lt-ie9 &amp; {
@content;
}
}
@media (#{$query1}-#{$query2}: map-get($tweakpoints, $point) / $sassifaction-font-size + 0em) {
@content;
}
}
@else if map-has-key($breakpoints, $point) {
@if $ie == true{
.lt-ie9 &amp; {
@content;
}
}
@media (#{$query1}-#{$query2}: map-get($breakpoints, $point) / $sassifaction-font-size + 0em) {
@content;
}
}
@else {
@warn 'Could not find the value <code>#{$point}</code> in either local ($tweakpoints) or global ($breakpoints) contexts. Media block omitted.';
}
}</p>
<p>So here, as per Hugo’s mixin we’re looking for a local <code>$point</code> in <code>$tweakpoints</code> and if there’s not one available from that Sass map the mixin will then look for a global <code>$point</code> in <code>$breakpoints</code> and finally failing silently with a <code>@warn</code> notice if neither are available.</p>
<p>Unlike Hugo’s mixin I’m converting my media to ems still, although pretty much a moot point now as <a href="http://blog.cloudfour.com/the-ems-have-it-proportional-media-queries-ftw/">proportional media queries</a> work with both <code>px</code> and <code>em</code>. I’m sticking with declaring them in ems so I know it can work on as many browsers as possible.</p>
<h2 id="the-best-of-both-worlds" tabindex="-1">The best of both worlds</h2>
<p>I’m pretty happy with what I’ve got now. I’ve got the increased option of modularity with components I create and the ability to define what type of media query I’m using (up to a point). I’ve also created it’s own litle <a href="https://github.com/sturobson/sassifaction-mq">Github Repo</a> where I’m trying to work out how to get it working with bower, ruby gems and the forthcoming <a href="https://github.com/sass-eyeglass/eyeglass">eyeglass</a> too. A work in progress, that side of the development is, thus far.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Organising Your Grunt Tasks</title>
      <link href="https://www.alwaystwisted.com/articles/organising-your-grunt-tasks.html"/>
      <updated>2015-02-27T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/organising-your-grunt-tasks.html</id>
      <content type="html">
        <![CDATA[
        <p>I've been slowly and steadily working on <a href="https://github.com/sturobson/squealer">Squealer</a> in my spare time and evenings recently. Trying to create a set of 'starter files using <a href="http://www.gruntjs.com">Grunt</a>. Squealer isn't really a new project. I did have a very old 'first attempt' at something using Grunt when the task runner was pretty fresh to the industry.</p>
<p>One thing I didn't like about it was the huge Gruntfile.js I was creating at the time, luckily this is something I was able to address in this iteration. Instead of <a href="http://www.html5rocks.com/en/tutorials/tooling/supercharging-your-gruntfile/">spitting out</a> all of the plugins code into one file I could simply abstract them out into their own separate .js file.</p>
<p>Now my Gruntfile.js is simply</p>
<p>module.exports = function (grunt) {
'use strict';
require('load-grunt-config')(grunt);
require('time-grunt')(grunt);
};</p>
<p>Using this I now have a folder, called grunt, where I store these separate .js files which gets pulled in. What I have to work with this now is a <a href="https://github.com/sturobson/squealer/blob/master/grunt/aliases.yml">aliases.yml file</a> that contains several options when using Grunt.</p>
<h2 id="not-just-javascript-and-sass" tabindex="-1">Not Just JavaScript and Sass</h2>
<p>I don't just want my Grunt task runner to compile Sass, uglify JS and minify all the things. The great thing with Grunt (and Gulp and others too) is the great plugins directory that is available. I've got plugins for image optimisation, for sprite generation, performance tests, creating a styleguide, prefixing CSS with vendor prefixes and more.</p>
<p>I don't really want to run 'all the things' I've got in my task runner running at the same time. Do I really need to be making sure I optimise every image I include whilst I'm developing the site, or can that wait? Do I need CSS file size calculations everytime I change something in Sass that gets compiled? Do I <em>really</em> need all the vendor prefixes when I'm using a browser that supports 99% of what I use, even CSS3 animations? What about generating that styleguide, does that have to happen on each new Sass partial created?</p>
<h2 id="don't-run-everything-all-at-once" tabindex="-1">Don't run everything all at once</h2>
<p>Essentially the answers' no. Running everything at the same time will make things slower and waste a little bit of time. The great thing about that .yml file is I can easily split out the plugins I've included so I can choose and run some of the plugins at the same time. For example, when I'm developingg I only really want be compiling my Sass and Jade files. Minifying CSS and JavaScript files can wait. Optimising images can wait.</p>
<p>I won't be keeping an eye on the CSS file size and performance statistics every waking hour so they're in a separate task to when I'm creating the styleguides from my Sass partials. I'm probably going to only optimise my images on their own once in while or nearing the end of project before it gets on any server. So that task won't be included in a set of tasks to clean and minify my JavaSript and CSS including removing any unused CSS and creating a stylesheet for Internet Explorer 8 and below.</p>
<p>Currently I have groups of tasks for:</p>
<ul>
<li><a href="https://github.com/JamieMason/grunt-imageoptim">optimising images</a>.</li>
<li><a href="https://github.com/nDmitry/grunt-autoprefixer">prefixing CSS</a>, adding <a href="https://www.npmjs.com/package/grunt-px-to-rem">REMS to any PX</a> value, changing any URLs in CSS for the dev folder.</li>
<li>creating a stylguide from the 'MarkDown' in the Sass file.</li>
<li>cleaning and minifying JavaScript and CSS.</li>
<li>testing <a href="https://github.com/phamann/grunt-css-metrics">CSS metrics</a> before and after using <a href="https://github.com/addyosmani/grunt-uncss">UnCSS</a> to see any improvements.</li>
<li>a 'dev' build for compiling Sass, generating a <a href="https://www.npmjs.com/package/grunt-stripmq">stylesheet for older browsers</a> watching and pushing changes to browsers.</li>
</ul>
<p>It's not an exhaustive list but it allows for more specific development making any compile times that little bit quicker when working in the guts of a website: The HTML, CSS and JavaScript.</p>
<h2 id="making-it-work" tabindex="-1">Making it work</h2>
<p>The 'framework' <a href="https://github.com/sturobson/squealer">Squealer</a> is still a work in progress. The YAML file containing the grunt plugins tasks will be changing to make it more 'specific' to tasks needing to be run. I've a few more plugins I want to include too. Bower is something I need to look at to call in things like jQuery and put it where it's needed in the folder structure.</p>
<p>Hopefully from this you've seen a nice logical jump to abstracting your Grunt plugins into separate files and also benefit in splitting out the tasks you need to run into separate groups as needed.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Rethinking Your Sass Variables</title>
      <link href="https://www.alwaystwisted.com/articles/rethinking-your-sass-variables.html"/>
      <updated>2015-02-26T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/rethinking-your-sass-variables.html</id>
      <content type="html">
        <![CDATA[
        <p>Using variables in Sass or any other preprocessor makes it easier to populate your stylesheets easily without having to remember the exact hexadecimal code for the <a href="http://www.lukew.com/ff/entry.asp?1469">Facebook blue 261 times</a>.</p>
<p>As well as making it easier on the developer to use something like <code>$brand-color--primary</code> instead of <code>#D37E4A</code> using a variable means if you need to change the shade of your clients main brand colour by a smidgen across the site, it's relatively easy to do so.</p>
<p>This is all good, but can we take our variables partial too far. Listening to an episode of <a href="http://www.shoptalkshow.com/episodes/153-mark-otto/">The ShopTalk Show</a> where <a href="http://www.css-tricks.com/">Chris</a> and <a href="http://www.daverupert.com/">Dave</a> talk to <a href="http://www.markdotto.com/">Mark Otto</a>, amongst other things, about <a href="http://www.getbootstrap.com/">Bootstrap</a>. At some point Mark mentions that the <a href="https://github.com/twbs/bootstrap-sass/blob/master/assets/stylesheets/bootstrap/_variables.scss">variable partial</a> in the UI library has around <a href="https://github.com/twbs/bootstrap-sass/blob/master/assets/stylesheets/bootstrap/_variables.scss#L862">860 lines</a> and that navigating it can be a bit laborious because it's so long.</p>
<p>My, pretty basic, <a href="https://github.com/sturobson/Sassifaction/blob/master/sass/_variables.scss">Sass variable partial</a> is only 80 lines or so. Not huge by any means but they're still all in one place.</p>
<h2 id="patterns" tabindex="-1">Patterns</h2>
<p>After reading <a href="https://twitter.com/ianfeather">Ian Feather's</a> article on <a href="http://ianfeather.co.uk/what-we-would-change-about-rizzo/">what Lonely Planet would change</a> about <a href="https://github.com/lonelyplanet/rizzo">Rizzo</a> I created a new repo, <a href="https://github.com/sturobson/patterns">patterns</a>, where hopefully overtime I'll include sanitised patterns used in projects, that include the relevant HTML, CSS (probably Sass) and JavaScript (if needed).</p>
<p>It's probably re-inventing the wheel a little as there's already projects like <a href="http://getbootstrap.com/">Bootstrap,</a>, <a href="http://foundation.zurb.com/">Foundation</a>, <a href="http://refills.bourbon.io/">Refills</a> that include ready made components and patterns to use but as I've <a href="../post.php%EF%B9%96s=2014-02-27-codelicious.html">previously mentioned</a> I'd 'be happy in the knowledge of what every line of code I produce is doing'' and the idea of patterns is that I only really have to do the main bulk of the coding once.</p>
<h2 id="base-and-component-variables" tabindex="-1">Base and Component Variables</h2>
<p>After reading <a href="https://twitter.com/hugogiraudel">Hugo's</a> article on <a href="http://www.sitepoint.com/breakpoints-tweakpoints-sass/">Breakpoints and Tweakpoints in Sass</a> on <a href="http://www.sitepoint.com/">SitePoint</a> where he shows a <em>really</em> neat idea in creating a CSS Media Queries mixin to allow for 'global' breakpoints that are more suited to overall layout decisions and component based breakpoints, <a href="https://adactio.com/journal/6044">'tweakpoints'</a> for 'polishing the look and feel of the page''.</p>
<p>I've been thinking this would work really well for other variables too. To have a (small) list of variables for site wide values like font families, colours, gutters, and so on which can either be called into a component with it's own variables which would then allow those component variables to be overridden.</p>
<p>For example, we would have a main variables file:</p>
<p>//  Default Variables
//  --------------------</p>
<p>$brand-color--primary: #C69;
$brand-color--secondary: #699;
$brand-color--tertiary: #F2ECE4;</p>
<p>...</p>
<p>And then we would have a component variables file. Something like:</p>
<p>//  Tabs Pattern
//  -------------------</p>
<p>$tabs-navigation-border-color: $brand-color--secondary;
$tabs-navigation-text-color: $brand-color--tertiary;</p>
<p>$tabs-main-background-color: $white;</p>
<p>...</p>
<p>Here we would have the various variables relating to the pattern named to match the pattern. This can take in variables from our global file <code>$tabs-navigation-text-color</code> using <code>brand-color--tertiary</code> for example. It also gives you the option to override and replace the global variable with whatever is required.</p>
<h2 id="nothing-is-new" tabindex="-1">Nothing Is New</h2>
<p>Having decided upon creating 'component' and 'global' variables over the last couple of weeks I often felt that this idea cannot be new. There must be another front-end developer, agency, or software company that has been 'rolling their Sass' like this for quite a while.</p>
<p>After a <a href="https://twitter.com/StuRobson/status/569181837500792832">quick tweet</a> to Mark last night consultant front-end architect <a href="http://www.csswizarday">Harry Roberts</a> <a href="https://twitter.com/csswizardry/status/569182273242832897">replied</a> saying that this is an idea he has been employing in <a href="https://github.com/inuitcss">Inuit</a> for a while now.</p>
<p>You could argue that this just takes things a little too far, but I think it makes sense. Rather than going through a document of 800 or so variables to see the <code>$jumbotron-border-color</code> is the same as the <code>$brand-color--primary</code> at the top of that file seems a little laborious and having the variable for a 'Jumbotron' component within the rest of the CSS makes it much to check and to edit if need be.</p>
<h2 id="turn-and-face-the-change" tabindex="-1">Turn And Face The Change</h2>
<p>There's a chance I might change my mind on this. The underlying idea around <a href="http://www.github.com/sturobson/patterns">patterns</a> is for me to have some 'go to' code for client projects so that I don't have to reinvent my wheel on each project.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>LDN_Sass</title>
      <link href="https://www.alwaystwisted.com/articles/ldnsass.html"/>
      <updated>2014-07-24T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/ldnsass.html</id>
      <content type="html">
        <![CDATA[
        <p>So, this morning I was looking through my twitter feed (I'm on twitter quite a bit) and I saw tweets about how well a <a href="https://twitter.com/themixinsf">Sass meetup</a> in San Francisco went (and that most attendees were signed up to <a href="https://twitter.com/sassnews">SassNews</a>).</p>
<p>I've always wanted to run some form of local meetup. In Salisbury there's not really much of 'a scene' as far as I know. Being a huge fan of Sass what I really wanted was a Sass meetup to go to.</p>
<p>So, taking the bull by the horns and after a flurry of DMs with friends that ran conferences and meetups I've decided to throw my hat in the ring.</p>
<h3 id="ldn_sass%2C-london%3F" tabindex="-1">LDN_Sass, London?</h3>
<p>As Sass is, effectively, quite a nuanced subject in web design still I've decided to hold the meetup(s) that I'm hoping to run in London. I have several developer friends in London and it's not that too far a stretch on the train.</p>
<h3 id="moving-forward" tabindex="-1">Moving Forward</h3>
<p>Obviously, I've not thought this through that greatly. I mean, the first date I picked was the day I would be flying out to Italy to speak at From The Front (<a href="http://2014.fromthefront.it/">tickets still available</a>).</p>
<h3 id="a-date" tabindex="-1">A date</h3>
<p>Wednesday the 24th of September is the date. I've decided on a Wednesday purely selfishly as this is the easiest day of the week for me to get to London and back.</p>
<h3 id="a-helping-hand" tabindex="-1">A helping hand</h3>
<p>For now I'm making the list of everything else I need. A venue, speakers, A/V equipment, food, drinks, sponsors, a nicer logo, stickers, a website(?) and probably a hundred other things that I've forgotten.</p>
<p>So, if you can help with any of the above then just get in touch. Leave a comment below, <a href="mailto:stu@alwaytwsited.com">email me</a> or ping me on <a href="http://www.twitter.com/sturobson/">twitter</a>.</p>
<p>I'm looking forward to it, as much as organising it as to spend an evening with fellow developers who use Sass.</p>
<p>For updates, for the moment it's probably best to <a href="http://www.twitter.com/LDN_Sass">follow @LDN_Sass</a></p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Talkin&#39; &#39;bout Z-Index</title>
      <link href="https://www.alwaystwisted.com/articles/talkin-bout-z-index.html"/>
      <updated>2014-07-22T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/talkin-bout-z-index.html</id>
      <content type="html">
        <![CDATA[
        <p>Every now and then I see a tweet or read an article about z-index. It always bemuses me a little. I rarely find myself trying to figure out the stack of elements with z-index. Perhaps it's the work I do. I don't think that's the case because, being a jobbing freelancer, the work is forever varied.</p>
<p>I've never been a fan of z-index: 9999; the temptation just to make up long numbers to really make sure that the component will be on top is just a little too silly for my liking.</p>
<p>So, for the last 12 months or so I've been using what I call the 'Van Halen method'.</p>
<p>812
1984
5150</p>
<p>Of course, this isn't really any different from 9999, 99999 and 999999 but stipulating the numbers gives me some form of system to make sure I adhere to.</p>
<p>Taking the groups albums titles with numbers in it I've rarely, if ever, found myself needing more than these three options for z-index.</p>
<p>Of course, there's the potential in 6,9,12,24 months that I'll come back to this and laugh at myself. For the moment and for the last year, for me, it's worked perfectly.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Getting .liquid working with Emmet in Atom</title>
      <link href="https://www.alwaystwisted.com/articles/getting-liquid-working-with-emmet-in-atom.html"/>
      <updated>2014-07-04T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/getting-liquid-working-with-emmet-in-atom.html</id>
      <content type="html">
        <![CDATA[
        <p>I've been using <a href="https://atom.io/">Atom</a> for quite some time now, I managed to snag a beta invite on the day it was released and I've been enjoying seeing it improve and all the new plugins and themes that I manage to come across almost daily.</p>
<p>I do have a problem however.</p>
<p>Predominantly I use <a href="http://mixture.io/">Mixture</a> for my front-end development work. Mixture uses the <a href="http://liquidmarkup.org/">liquid language</a> to let you do <a href="http://docs.mixture.io/templates">some funky things</a>. I also like using <a href="http://emmet.io/">Emmet</a> so that I don't have to labouriously write out HTML and CSS.</p>
<p>Unfortunately the <a href="https://github.com/emmetio/emmet-atom">Emmet plugin</a> doesn't seem to <a href="https://github.com/emmetio/emmet-atom/issues/102">recognise the .liquid file type</a> and adding the liquid language plugin to Atom <a href="https://github.com/atom/language-html/pull/30">doesn't seem to do anything either</a>.</p>
<p>But I found a fix.</p>
<p>If you open your preferences in Atom (cmd + P) then filter through your installed packages for the language HTML package, open it.</p>
<p>Then guide yourself to the file called html.json which is in the folder 'grammars'.</p>
<p>At the top of the file (html.json) there will be a list of file types including HTML, SHTML, XHTML etc.</p>
<p>Follow the .json format and add 'liquid' to the bottom.</p>
<p>Save and close the file, close that window for that package.</p>
<p>Reload your project and you should find that you can now use all the emmet shortcodes and shortcuts in your liquid files.</p>
<p>Easy. Apart from this needs to be done on every update of Atom.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Sass: An introduction. A workshop at WebDevConf</title>
      <link href="https://www.alwaystwisted.com/articles/sass-an-introduction-a-workshop-at-webdevconf.html"/>
      <updated>2014-05-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/sass-an-introduction-a-workshop-at-webdevconf.html</id>
      <content type="html">
        <![CDATA[
        <p>I'm really happy to finally announce I'm hosting a half day workshop for Webdevconf in Bristol in October. I've been an attendee for the last 4 years and Axex does an amazing job getting everything running smoothly.</p>
<h2 id="what-will-i-learn%3F" tabindex="-1">What Will I Learn?</h2>
<p>The workshop will give you the tools and skills to make you write better CSS by applying the benefits of Sass. Using both hands-on exercises (by taking a design and coding) and tuition the workshop will cover:</p>
<ul>
<li>Options for installing Sass on your machine</li>
<li>The two syntaxes, Sass &amp; SCSS</li>
<li>Variables, mixins and includes</li>
<li>Extends and placeholders</li>
<li>Built in functions</li>
<li>Media queries &amp; nesting</li>
<li>Compass, Bourbon and other frameworks</li>
<li>Sass and front-end performance</li>
<li>And more!</li>
</ul>
<p>Please bring your laptop (hopefully with Sass installed) as this will in part be a practical workshop.</p>
<h2 id="about-the-event" tabindex="-1">About the event</h2>
<p>WDC (webdevconf) is a one day conference held in Bristol each year around the start of October. This year Alex has added workshops to the conference that run the day before. My workshop (Sass: An Introduction) will run on Thursday 9th October 2014 in the afternoon.</p>
<p><a href="http://2014.webdevconf.com/workshops/#sturobson">- Tickets are available here -</a></p>
<h2 id="testimonials" tabindex="-1">Testimonials</h2>
<p>Here are a few testimonials from previous workshop attendees.</p>
<blockquote>
<p>“Stu did a fantastic job making Sass accessible to beginners. The workshop was incredibly practical, light on preaching and heavy on pragmatism. Even an old dog like me, came away wanting to give Sass another go. Highly recommended!”</p>
<p>Alex Morris - <a href="http://www.adobe.com/">Adobe</a></p>
</blockquote>
<blockquote>
<p>“The workshop was well balanced, Stuart shared examples and got us using Sass within minutes of the workshop starting, it was a practical hands-on introduction from a clear expert. The relaxed &amp; informal setting made it a pleasure to attend. ”</p>
<p>Steve Kirkley - <a href="http://www.twitter.com/stevekirtley">@stevekirtley</a></p>
</blockquote>
<blockquote>
<p>“Stu’s knowledge of Sass and his way of explaining the ins and outs, for me, are unparalleled to anyone else I know.  Highly recommended if you are new to Sass, or are interested in increasing your understanding of this wonderful language.”</p>
<p>Nick Toye - <a href="http://www.nicktoye.co.uk/">Pixels &amp; Code</a></p>
</blockquote>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Speaking at From the Front 2014</title>
      <link href="https://www.alwaystwisted.com/articles/speaking-at-from-the-front-2014.html"/>
      <updated>2014-05-19T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/speaking-at-from-the-front-2014.html</id>
      <content type="html">
        <![CDATA[
        <p><img src="http://www.alwaystwisted.com/blog/fromthefront.jpg" alt="from the front logo" loading="lazy" decoding="async"></p>
<p>It's safe to say I am _really_ excited about this.</p>
<p>In fact, I'm fantastically excited to announce that I'm speaking at this years From The Front in Bologna, Italy.</p>
<p>The organisers are pulling out all the stops and there's some amazing speakers already announced with more to be announced in the lead up to the event. They're keeping a tight lip, and I'm really excited to see who else I'll get to 'strut the stage' with.</p>
<p>My mind is buzzing with Indiana Jones references, I might even 'dress up'. I'm really looking forward to going to Italy not only for the conference but obviously for all that food and drink. The idea of a calzone made to order is making me salivate.</p>
<p>But I digress...</p>
<p>I'll be shouting about the ups and downs of the menagerie of HTML and CSS frameworks and boilerplates available and why you should really think about what you're using and making your code delicious, like <a href="../post.php%EF%B9%96s=2014-02-27-codelicious.html">lasagne</a>.</p>
<h2 id="some-conference-information" tabindex="-1">Some conference information</h2>
<p>From The Front, is a two day, one track conference in Bologna, Italy. Running on the 18th and 19th of September 2014. Tickets and more information are available here:</p>
<p><a href="http://2014.fromthefront.it/">http://2014.fromthefront.it/</a></p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Sass, a whistle stop tour</title>
      <link href="https://www.alwaystwisted.com/articles/sass-a-whistle-stop-tour.html"/>
      <updated>2014-03-14T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/sass-a-whistle-stop-tour.html</id>
      <content type="html">
        <![CDATA[
        <p>On Wednesday 12th of March I thought I'd grab <a href="http://www.twitter.com/richargwiggins">Richard Wiggins</a> for a quick second pair of eyes on some designs I've been doing over the last couple of days. We chatted about it and I mentioned the tweet I saw earlier in the day about one of the speakers for the <a href="http://mkgeeknight.co.uk/">MK (Milton Keynes) Geek Night</a> he co-organises with <a href="http://www.twitter.com/davidhughes">Dave Hughes</a> having to drop out. I asked Richard if he found a replacement for the spot. He hadn't. He asked me. I had a quick think of what I could do in (around) 5 minutes and said yes.</p>
<p>As you'll all more likely know that I like Sass I thought I'd talk about that. I didn't want to do a talk about how to get up and running with Sass on your machines and get writing your first lines of code. I wanted to try and debunk some often aired views (which I hope at a later date to blog about fully).</p>
<p>I got my copy of Keynote out and started hacking away at slides I've got for my workshops and trying to tie a nice 'story' or 'adventure' together.</p>
<p>I'm truly amazed and thankful that on the even my friend <a href="http://twitter.com/bseymour">Ben Seymour</a> decided to hold his phone still for 8/9 minutes and record my talk albeit a little flustered at times.</p>
<p>Here's the audio recording of the talk</p>
<p>I've also put <a href="https://speakerdeck.com/sturobson/sass-a-whistle-stop-tour">slides on speakerdeck</a>.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Using Sass 3.3s @at-root for piece of mind</title>
      <link href="https://www.alwaystwisted.com/articles/using-sass-33s-at-root-for-piece-of-mind.html"/>
      <updated>2014-03-08T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/using-sass-33s-at-root-for-piece-of-mind.html</id>
      <content type="html">
        <![CDATA[
        <p>I often discuss on this site how I like to have ‘clarity’ or ‘cleanliness’ and order when writing my CSS/Sass. I also at some points state how the browser doesn’t give two hoots about your indentation or if you're ordering things alphabetically or not.</p>
<p>In thinking about keeping my code in check to keep my sanity also I’ve just recently ‘fell in love’ with the new @at-root directive coming in Sass 3.3.</p>
<p>With CSS3 we’ve been given some fantastic options with animations. Some developers are doing some really, really excellent work demoing these possibilities. It’s fantastic, but I have a slight problem with the syntax.</p>
<p>When I’m writing my Sass/CSS for to animate an element. I’ve never been a fan of having the @keyframe syntax outside of the element I want animating. Obviously this is great because of reusability of the same @keyframe ruleset but sometimes if gives me a level of abstraction I just cannot grok, and it looks messy (not that that matters).</p>
<h2 id="in-comes-sass-3.3s-new-%40at-root-directive" tabindex="-1">In comes Sass 3.3s new @at-root directive</h2>
<p>It’s the @at-root directive. It works by ‘jumping out’ of where you nest it in your Sass to be a the top level. For example you could use it simply like this:</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">h1 </span><span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 16px<span class="token punctuation">;</span>
  <span class="token atrule"><span class="token rule">@at-root</span></span> <span class="token punctuation">{</span>
    <span class="token selector">header </span><span class="token punctuation">{</span>
      <span class="token property">margin</span><span class="token punctuation">:</span> 0 auto<span class="token punctuation">;</span>
      <span class="token property">width</span><span class="token punctuation">:</span> 98%<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Which would print out the resulting CSS like this:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">h1</span> <span class="token punctuation">{</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 16px<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">header</span> <span class="token punctuation">{</span>
  <span class="token property">margin</span><span class="token punctuation">:</span> 0 auto<span class="token punctuation">;</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 98%<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>One quick thing to note on this is that it prints whatever is in the @at-root after rather than before where it’s been nested.</p>
<p>Since seeing this it’s taken me a while to work out where I’d find a use for it. Which brings us back to animations.</p>
<p>So, perhaps you’re making some things on your site animate. It’d be awesome if you could include those @keyframes when you’re writing the calls to it in your CSS right? You can’t because it won’t get recognised as @keyframes need to be outside, at the root of the CSS.</p>
<h2 id="at-the-root-of-the-css" tabindex="-1">At the root of the CSS</h2>
<p>Let’s for examples sake say we want to animate the scale of an avatar when visitors hovered over it. So you would write your CSS for the .avatar, something like this.</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.avatar </span><span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> red<span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> 120px<span class="token punctuation">;</span>
  <span class="token property">margin</span><span class="token punctuation">:</span> 40px<span class="token punctuation">;</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 120px<span class="token punctuation">;</span>
  <span class="token selector"><span class="token parent important">&amp;</span>:hover </span><span class="token punctuation">{</span>
    <span class="token property">animation</span><span class="token punctuation">:</span> sizeme 0.8s infinite ease-in alternate<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>For this we’d then need to make some @keyframes for sizeme so that it works. Something (ridiculous for example) like this.</p>
<pre class="language-css"><code class="language-css"><span class="token atrule"><span class="token rule">@keyframes</span> fade</span> <span class="token punctuation">{</span>
  <span class="token selector">0%</span> <span class="token punctuation">{</span>
    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">25%</span> <span class="token punctuation">{</span>
    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1.1<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">50%</span> <span class="token punctuation">{</span>
    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">75%</span> <span class="token punctuation">{</span>
    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1.2<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">100%</span> <span class="token punctuation">{</span>
    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1.1<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Ok, but how about adding that @keyframe into the SCSS rather than outside it so it’s ‘together’. Well, with Sass 3.3s new @at-root directive you can write something like this.</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.avatar </span><span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> red<span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> 120px<span class="token punctuation">;</span>
  <span class="token property">margin</span><span class="token punctuation">:</span> 40px<span class="token punctuation">;</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 120px<span class="token punctuation">;</span>

  <span class="token atrule"><span class="token rule">@at-root</span></span> <span class="token punctuation">{</span>
    <span class="token atrule"><span class="token rule">@keyframes</span> fade</span> <span class="token punctuation">{</span>
      <span class="token selector">0% </span><span class="token punctuation">{</span>
        <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      <span class="token selector">25% </span><span class="token punctuation">{</span>
        <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1.1<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      <span class="token selector">50% </span><span class="token punctuation">{</span>
        <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      <span class="token selector">75% </span><span class="token punctuation">{</span>
        <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1.2<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      <span class="token selector">100% </span><span class="token punctuation">{</span>
        <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1.1<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
  <span class="token selector"><span class="token parent important">&amp;</span>:hover </span><span class="token punctuation">{</span>
    <span class="token property">animation</span><span class="token punctuation">:</span> fade 0.8s infinite ease-in alternate<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>And it would print out CSS like this</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.avatar</span> <span class="token punctuation">{</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> red<span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> 120px<span class="token punctuation">;</span>
  <span class="token property">margin</span><span class="token punctuation">:</span> 40px<span class="token punctuation">;</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 120px<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token atrule"><span class="token rule">@keyframes</span> fade</span> <span class="token punctuation">{</span>
  <span class="token selector">0%</span> <span class="token punctuation">{</span>
    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">25%</span> <span class="token punctuation">{</span>
    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1.1<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">50%</span> <span class="token punctuation">{</span>
    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">75%</span> <span class="token punctuation">{</span>
    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1.2<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">100%</span> <span class="token punctuation">{</span>
    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">scale</span><span class="token punctuation">(</span>1.1<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token selector">.avatar:hover</span> <span class="token punctuation">{</span>
  <span class="token property">animation</span><span class="token punctuation">:</span> fade 0.8s infinite ease-in alternate<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>So that the animation works. You could also use the @at-root for something like @supports too.</p>
<p>Here's a <a href="http://sassmeister.com/gist/9408093">gist of the example above</a> on Sassmeister.</p>
<p>What ways can you think of that’d be a great use of the new @at-root?</p>
<hr>
<p>So you obviously love Sass. So how about <a href="http://eepurl.com/ErvvT">signing up to a weekly newsletter</a> of all things Sass direct to your inbox, curated by me?</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Even Better @each loops with Sass 3.3</title>
      <link href="https://www.alwaystwisted.com/articles/even-better-each-loops-with-sass-33.html"/>
      <updated>2014-03-06T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/even-better-each-loops-with-sass-33.html</id>
      <content type="html">
        <![CDATA[
        <p>In the not to distant future Sass 3.3 is going to land for the masses outside of it’s pre-release cycle. I’ve already discussed how they’ve now made things like <a href="../post.php%EF%B9%96s=2014-02-27-even-easier-bem-ing-with-sass-33.html">BEM in your CSS even easier</a>. So I’d thought I’d touch on something else that’s on it’s way that’s pretty Sass-y.</p>
<p>With Sass 3.2 you can easily generate some CSS based on a list of ‘things’. Perhaps you wanted to have some social links on a site and wanted to have the background of each relevant link the association colour of that social network.</p>
<p>You’d probably make some variables like this to start with:</p>
<p>$Twitter: #41b7d8;
$FB: #3b5997;
$GPlus: #d64937;
$LinkedIn: #0073b2;</p>
<p>You could then add these into a list ready to be pulled into the @each loop:</p>
<p>$social-colours: $Twitter, $FB, $GPlus, $LinkedIn;</p>
<p>You’d then write some Sass like this to get the @each to loop through the list and generate the relevant CSS:</p>
<p>li {
float: left;
height: 48px;
list-style: none;
width: 100%;
}
@for $i from 1 through length($social-colours) {
li:nth-of-type(#{$i}) {
background: nth($social-colours, $i);
}
}</p>
<p>That in turn, when printed out would give a result like this:</p>
<p>ul li {
float: left;
height: 48px;
list-style: none;
width: 100%;
}
ul li:nth-of-type(1) {
background: #41b7d8;
}
ul li:nth-of-type(2) {
background: #3b5997;
}
ul li:nth-of-type(3) {
background: #d64937;
}
ul li:nth-of-type(4) {
background: #0073b2;
}</p>
<p>That in itself is pretty cool right? You may want to add another link at a later date. All you’ve gotta do is tap on another colour (or $variable) at the end and it’d get printed out in your CSS.</p>
<h2 id="but-we-want-more-than-one-thing-in-the-list" tabindex="-1">But we want more than one thing in the list</h2>
<p>As you can see from the example above I’ve used nth-of-type to style each li differently. What if I wanted to give my li a class of the relevant social network? Perhaps I want to add an icon in each li too?</p>
<p>Well you could create more lists, but that can be a bit cumbersome and isn’t as tidy as answer.</p>
<p>With Sass 3.3 you have the ability to have can create a list of lists and then use the @each directive to make some Sass-y outputted CSS.</p>
<p>So going back to our crude example. Rather than use nth-of-type let’s give each printed li it’s own class name relevant to the social network.</p>
<p>Keeping our original set of variables above we could then make a new list like this:</p>
<p>$social: (twitter, $Twitter),
(facebook, $FB),
(googleplus, $GPlus),
(linkedin, $LinkedIn);</p>
<p>So above you can see from a glance what’s going on, nice and simple. Now lets uses those lists in the list to create some CSS.</p>
<p>@each socialnetwork, color in $social { }</p>
<p>Here we’ve given the two lists in the list social their own variable to be called upon in the curly braces. Let’s add more code.</p>
<p>@each $socialnetwork, $color in $social {
.social-link--#{$socialnetwork} {
background-color: $color;
&amp;:focus,
&amp;:hover {
background-color: darken($color,5%);
}
}
}</p>
<p>So here we’ve used the color as before but added the social network into the classname. This prints out some CSS like this:</p>
<p>.social-link--twitter {
background-color: #41b7d8;
}
.social-link--twitter:focus,
.social-link--twitter:hover {
background-color: #2cafd4;
}</p>
<p>.social-link--facebook {
background-color: #3b5997;
}
.social-link--facebook:focus,
.social-link--facebook:hover {
background-color: #344e85;
}</p>
<p>.social-link--googleplus {
background-color: #d64937;
}
.social-link--googleplus:focus
.social-link--googleplus:hover {
background-color: #ca3c29;
}</p>
<p>.social-link--linkedin {
background-color: #0073b2;
}
.social-link--linkedin:focus
.social-link--linkedin:hover {
background-color: #006399;
}</p>
<p>That’s pretty cool. Generating some tidy CSS through the new @each directive. You could then perhaps add a background icon if you wanted too. Just simply add another line of code to the example:</p>
<p>@each $socialnetwork, $color in $social {
.social-link--#{$socialnetwork} {
background-color: $color;
&amp;:focus,
&amp;:hover {
background-color: darken($color,5%);
}
&amp;:before {
background-image: url('/images/#{$socialnetwork}.png');
}
}
}</p>
<p>We’re getting somewhere nice and awesome here and this is just a quick example. I’m really looking forward to 3.3 dropping for real. I think it’s pretty stable at the moment to give it a whirl. Don’t forget it’s now available in <a href="http://www.codepen.io">CodePen</a> and <a href="http://www.sassmeister.com">Sassmeister</a>.</p>
<p>The example above is <a href="http://sassmeister.com/gist/9378629">available here</a> to peruse and pick apart</p>
<p>How do you think you can make use of the new lists within lists @each directive?</p>
<hr>
<p>So you obviously love Sass. So how about <a href="http://eepurl.com/ErvvT">signing up to a weekly newsletter</a> of all things Sass direct to your inbox, curated by me?</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>My Shed</title>
      <link href="https://www.alwaystwisted.com/articles/my-shed.html"/>
      <updated>2014-02-27T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/my-shed.html</id>
      <content type="html">
        <![CDATA[
        <p>More often than not I probably open a new <a href="http://codepen.io/">CodePen</a> at least 20-30 times a day. I don’t keep count. That’d be silly.</p>
<h2 id="i-%3C3-codepen" tabindex="-1">I &lt;3 CodePen</h2>
<p>If I need to quickly thrash out how I’m going to code something I jump straight into CodePen before I open an IDE. If someone on twitter asks a Sass/CSS question I open a new pen to play with it for a minute or two. <a href="http://codepen.io/sturobson/">I frickin’ love CodePen</a>.</p>
<h2 id="my-shed" tabindex="-1">My Shed</h2>
<p>It’s become my (digital) <a href="http://hicksdesign.co.uk/journal/the-shed">‘shed’</a>. Where I go to and tinker with and fettle code whether I need it for a project or just for fun.</p>
<h2 id="great-for-clients" tabindex="-1">Great for clients</h2>
<p>Going back to last October I was working on a site for a client in London. There were quite a few interactions on the pages that needed to be animated when the visitor hovered over them.</p>
<p>I instantly thought that by making a private CodePen (available with <a href="http://codepen.io/pro">a Pro account</a>) of each interaction I could then send them to the client for feedback. I was given a pdf of what each interaction should do, what should slide, move, animate and change colour etc. I then turned my interpretation of those descriptions into some lovely Sass-ified CSS for each one.</p>
<p>The client seemed really pleased with the idea of these ‘tiny little bootstraps’ and it made working out what they wanted into a reality so easy.</p>
<h2 id="get-a-shed" tabindex="-1">Get a shed</h2>
<p>If you’re not using CodePen I suggest you do. It’s so good to have your own shed.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>How I use my RSS</title>
      <link href="https://www.alwaystwisted.com/articles/how-i-use-my-rss.html"/>
      <updated>2014-02-27T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/how-i-use-my-rss.html</id>
      <content type="html">
        <![CDATA[
        <p>Last night at the Port80 spring #Localhost I touched on ways I ‘keep up’ in web development, now I’m working full-time in the industry instead of being on the peripherals as a night-owl freelancer.</p>
<p>After twitter, which I use once in a while, I rely on my collection of RSS feeds.</p>
<p>I’ve got around 400+ feeds hooked up to my feedbin account. Indeed that is a serious amount of feeds that can lead to a potentially huge number of posts at any given time I check.</p>
<h2 id="if-it-sounds-boring%2C-i%E2%80%99d-guess-it-is" tabindex="-1">If it sounds boring, I’d guess it is</h2>
<p>As I’ve got a potential huge amount of posts to go through I ‘attack’ my RSS in 3 stages.</p>
<p>First off I go through the whole list and then ‘mark as read’ any posts where the title doesn’t interest me. A little harsh but I don’t think this has affected my reading up on things over the last year or so.</p>
<p>Secondly, after I’ve done this I generally open up each post that’s left and have a quick skim read. If it still seems interesting I think ‘mark as unread’ to read later. Which is basically step 3.</p>
<h2 id="but-that-still-takes-time" tabindex="-1">But that still takes time</h2>
<p>Of course, at the end of the day, this still takes time. I find time though. Be it those few minutes before I fall asleep in bed (when the iPhone whacks me on the head) or waiting for the kettle to boil for a nice cup of joe.</p>
<h2 id="tweeting-what-i-like" tabindex="-1">Tweeting what I like</h2>
<p>If time is on my side I often go through a tweeting spree of posts that I read in step 3 that I hope people that follow me would find interesting too.</p>
<h2 id="%23fastidious" tabindex="-1">#fastidious</h2>
<p>So to get me to read your post first off I need an interesting title, fastidious I know.</p>
<p><a href="https://www.dropbox.com/s/d0e22k6mn2w4ikz/RSS.xml">Here’s a link to my current collection of RSS feeds as an XML file</a>.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Even Easier BEM-ing with Sass 3.3</title>
      <link href="https://www.alwaystwisted.com/articles/even-easier-bem-ing-with-sass-33.html"/>
      <updated>2014-02-27T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/even-easier-bem-ing-with-sass-33.html</id>
      <content type="html">
        <![CDATA[
        <p>Back in October last year (2013) <a href="http://blog.unakravets.com/post/64113156740/sass-3-3-at-root-bem">Una wrote a blog post</a> about using Sass 3.3s new @at-root directive to create some sexy easy BEM nesting possibilities.</p>
<p>BEM (Block, Element, Modifier) from <a href="http://bem.info/method/">Yandex</a> allows developers to create a simple naming convention helping make your CSS more modular and portable.</p>
<p>.block{} // the ‘thing’ like .list
.block__element{} // a child of the block like .list__item
.block--modifier{} // a variation of the ‘thing’ like .list-—vertical</p>
<p>Using the way Una described you would write some Sass like this ...</p>
<p>.block {
@at-root #{&amp;}__element {
}
@at-root #{&amp;}--modifier {
}
}</p>
<p>... which would print out like this ...</p>
<p>.block {}
.block__element {
}
.block--modifier {
}</p>
<p>When Sass 3.3.0rc3 came out a couple of weeks ago they changed this. For the better. <a href="http://www.twitter.com/nex3">Natalie</a> explains the goings on in <a href="http://nex3.roughdraft.io/8050187">this gist</a> (via <a href="http://jedfoster.com/">Jed Fosters</a> <a href="http://www.roughdraft.io/">roughdraft.io</a>).</p>
<p>Now instead of needing ugliness of @at-root #{&amp;} which in honesty was putting me off, you can now just use the ampersand. This makes your Sass look so much nicer (not that <em>that</em> matters) and quicker to write, obviously.</p>
<p>So now you would write some Sass like this ...</p>
<p>.block {
&amp;__element {
}
&amp;--modifier {
}
}</p>
<p>... which now prints out like this ...</p>
<p>.block {}
.block__element {
}
.block--modifier {
}</p>
<p>I’m sure you can see how even sassier your Sass looks and the results remain the same.</p>
<p>For a ‘real world’ case of showing this technique and using BEM let’s have a look at some main navigation HTML</p>
<nav role='navigation' aria-label='primary'>
<ul class='nav__list'>
<li class='nav__list__item'>
<a href='' class='nav__link'></a>
</li>
<li class='nav__list__item'>
<a href='' class='nav__link--active'></a>
</li>
<li class='nav__list__item'>
<a href='' class='nav__link'></a>
</li>
</ul>
</nav><p>we could then write some Sass like this (being all BEM’y I’ve not added a class to the main nav (through personal choice)) ...</p>
<p>nav[role=navigation] {}
.nav {
&amp;__list {
&amp;__item {
}
}
&amp;__link {
&amp;--active {
}
}
}</p>
<p>You’d get this result.</p>
<p>nav[role=navigation] {
}
.nav {
}
.nav__list {
}
.nav__list__item {
}
.nav__link {
}
.nav__link--active {
}</p>
<p>That’s pretty sweet if you ask me, makes Sass nesting work nicely without giving too much to the inception rule to worry about. I’ve also gone on to make a version of <a href="http://sassmeister.com/gist/9228656">Harry Roberts’ Beautons</a> using it too.</p>
<p>What examples can you think of that this would be great for?</p>
<hr>
<p>So you obviously love Sass. So how about <a href="http://eepurl.com/ErvvT">signing up to a weekly newsletter</a> of all things Sass direct to your inbox, curated by me?</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>#codelicious</title>
      <link href="https://www.alwaystwisted.com/articles/codelicious.html"/>
      <updated>2014-02-27T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/codelicious.html</id>
      <content type="html">
        <![CDATA[
        <p>I love lasagne.</p>
<p>I can probably hazard a guess that it's actually because of Garfield that I love lasagne.</p>
<p>My mum made a mean lasagne. When I started to cook I think lasagne was one of the first three dishes I learned to cook. Whenever I've been out for a pub lunch that's not on any given Sunday I generally choose lasagne. Some are great, others not so much.</p>
<p>I make a mean lasagne. But it's a different to the lasagne my mum makes. I don't use a the herbs she does and I add half a tea spoon extra of balsamic vinegar. I also put a more than necessary amount of cheese on top.</p>
<p>You see with lasagne there's many ways you can make it a mean, lean tummy-filling machine and that, for me, is a great thing. It's why I love lasagne.</p>
<h2 id="wha--%3F" tabindex="-1">Wha- ?</h2>
<p>But what's this got to do with modern web development?</p>
<p>Well, I probably write code slightly differently to you. I use the margin and padding short-hand but not the font or background short-hand. I order my CSS rules alphabetically and order my SCSS rules in a certain way.</p>
<p>Yes, it all gets compiled and gzipped to a barely readable file when it goes live but that’s because the browser doesn’t care how you originally wrote it.</p>
<p>Using your own ‘framework’ or ‘boilerplate’ is the best way to hone your skill-set and improve for not only your benefit, but your clients and their customers.</p>
<p>It seems like so many new boilerplates, starting points and frameworks are being released it can seem to easy just to use something ‘off the shelf’. I seriously think this would be an injustice to yourself.</p>
<h2 id="the-starting-point" tabindex="-1">The starting point</h2>
<p>I guess we could say that the HTML5 boilerplate was the first, well ‘boilerplate’ for developers to quickly grab and hit the ground running with. It came with predefined ways of ‘doing things’ and a lovely <a href="https://github.com/h5bp/html5-boilerplate/issues/610">shade of pink</a> for when touching or selecting an element.</p>
<p>It still allowed developers to adapt and change to their own melt but invariable some used it verbatim without worrying or wondering why things were written in a certain way or even why they’re there to begin with.</p>
<h2 id="progressive-cookie-cutting" tabindex="-1">Progressive cookie cutting</h2>
<p>Moving forward developers took the idea of the boilerplate and expanded it, making things like <a href="http://getbootstrap.com/">Bootstrap</a> or <a href="http://foundation.zurb.com/">Foundation</a>. Coming along with some predefined objects and styles meant front-end developers could quickly flesh out a site with modules all ready to go.</p>
<h2 id="not-my-style" tabindex="-1">Not My Style</h2>
<p>I just can not do this. I’d much <a href="http://github.com/sturobson/Sassifaction">rather re-invent the wheel</a> a little and be happy in the knowledge of what every line of code I produce is doing even, for example, if I’m leaving Sass to do it’s ‘magic’ without worrying how’s its doing so.</p>
<p>I prefer to write my own mixins that suite my needs, code in a style that works with my (unfortunately, soon to be) cue ball noggin understanding it.</p>
<h2 id="beg%2C-borrow-and-steal" tabindex="-1">Beg, borrow and steal</h2>
<p>Don’t get me wrong, I often don’t write ‘everything’ uniquely without prior knowledge of things. Fundamentally I look through other starting points and frameworks see something that piques my interest and often drop it into my own set of starting files.</p>
<p>I’m just ‘careful’ or picky (or opinionated) in what I want to include and what I don’t.</p>
<h2 id="easier-to-take-away-than-to-add-it-after-you-launch" tabindex="-1">Easier to take away than to add it after you launch</h2>
<p>Generally, my starting point has ‘everyhing’ when I first start. I’ve got a link to respond.js in the <head>, there’s a link to the full latest Modernizr script and so on.</p>
<p>I find it easier to take away the things I don’t need as I move through developing a project rather than adding to it as needed (although there’s always a chance to add something still).</p>
<p>Many a time have I seen a new ‘responsive’ site launch that fails to work on my iPhone because they forgot to add the viewport meta tag.</p>
<h2 id="only-in-teams" tabindex="-1">Only in teams</h2>
<p>Anything you do with your starting point should of course be documented. If you’re in a team you want everyone to be ‘singing for the same hymn sheet’. If you hand over your work to a client then providing adequate documentation about your starting point and coding style will pave the way for them to easily see what you’re doing and why.</p>
<h2 id="a-quarter-pounder-with-cheese" tabindex="-1">A quarter pounder with cheese</h2>
<p>Writing your own set of starting files means you care about the details, the simple nuances of the code you’re using, making it ‘delicious’.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Talking at Port80&#39;s Spring Localhost</title>
      <link href="https://www.alwaystwisted.com/articles/talking-at-port80s-spring-localhost.html"/>
      <updated>2014-01-26T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/talking-at-port80s-spring-localhost.html</id>
      <content type="html">
        <![CDATA[
        <p>On February the 26th I’ll be in Newport at the Port80 Spring Localhost event, organised by the Joel Hughes.</p>
<p>As well as myself you will also have chance to hear <a href="http://twitter.com/garethstrange">Gareth Strange</a> from <a href="http://twitter.com/bluegg">Bluegg</a> talk about making time for personal projects and <a href="http://twitter.com/rumyra">Ruth John</a> who works for o2 discuss all the snazziness of Web Components.</p>
<p>This will be a first for me, not only a ‘new’ talk it will also see me trying to talk about something very personal rather than something somewhat technical or opinionated.</p>
<p>I’ll be telling the story of my first year of freelancing. The highs and the lows, the bacon, the weight gain. I’m hoping it’ll be a little bit more entertaining than that.</p>
<p>I hope to share insight into how I somehow ‘make things work’ and hope that people attending will an idea or something to riff on away with them.</p>
<p><a href="http://port80events.co.uk/event/spring-localhost-2014/">More info about the event from the site.</a></p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>An idea for smarter coding comments</title>
      <link href="https://www.alwaystwisted.com/articles/an-idea-for-smarter-coding-comments.html"/>
      <updated>2014-01-14T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/an-idea-for-smarter-coding-comments.html</id>
      <content type="html">
        <![CDATA[
        <p>I often write code quickly and refactor it as an on going process. I tend not to have a ‘written’ list of things that need ‘fixing’ and up until recently kept everything ‘in my head’ (a bonus of generally doing all the front-end development myelf).</p>
<p>I am currently working on an app for a client from Denmark wherein eventually the codebase will effectively ‘leave my hands’ to go to another developer to pull apart and integrate into their system.</p>
<h3 id="make-that-change" tabindex="-1">Make that change</h3>
<p>This time I thought I would start to actually write things down.</p>
<p>I could quite easily add a comment to my SCSS like this</p>
<p>height: 300px; // TODO: magic number to be removed</p>
<p>Starting all single line comments on code that needs to be fixed with the word TODO. I could then search through my project using Sublime Text (for example) and fix these things as and when before the other developers start cutting and slicing.</p>
<h3 id="make-it-easier" tabindex="-1">Make it easier</h3>
<p>I quickly got to thinking. Perhaps I could make my comments a little smarter. Rather than using the word TODO I could use a word that’s more ‘semantic’ to what needs fixing, looking at or refactoring.</p>
<p>For example I could take the above code and do this</p>
<p>height: 300px; // @magic</p>
<p>This would allude to what the comment is for, is easy to search groups of the same thing by.</p>
<p>Of course this could get tricky the more and I may need to create a glossary file of what the single worded comments mean.</p>
<p>I’m sure you can tell by the style of my writing that this is just a little brain-dump of an idea. It's probably not a even new idea.</p>
<p>(subject to change before 9am tomorrow morning and beyond.)</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Colour me Sass-y</title>
      <link href="https://www.alwaystwisted.com/articles/colour-me-sass-y.html"/>
      <updated>2014-01-07T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/colour-me-sass-y.html</id>
      <content type="html">
        <![CDATA[
        <p>I don’t tend to have to worry about what colours to use on a site. I generally don’t ‘design’ anymore and concentrate on coding the front-end of a project.</p>
<p>That being said, there’s times when I need to manipulate the colours I’m given in a design in the CSS. Maybe quickly make a brand colour have an alpha transparency on a overlay or some such other thing.</p>
<p>Sass helps me do this and more. The colour functions built into Sass are pretty amazingly mathematical and yet so easy to implement. In this post I’m going to quickly go through them all and mention a couple of ‘extra’ ones that are in Compass but not in Sass by default.</p>
<h3 id="darken-%26-lighten" tabindex="-1">darken &amp; lighten</h3>
<p>Two colour functions I often use when ‘playing’ around with some Sass ideas and sometime use, if appropriate, on client projects are darken and lighten. Each take the hex value of the colour (be it a hex value, rgb or $variable) you pass it, converts it into its HSL equivalent then makes the adjustments. The adjustment is declared as a percentage for these two functions.</p>
<p>.box-1 { background-color: lighten(#D13400, 30%); }
.box-2 { background-color: darken(#D13400, 30%); }</p>
<p>would give</p>
<h3 id="rgba" tabindex="-1">RGBa</h3>
<p>You can easily give the colour you’re using an alpha transparency. You give the colour you require a levle of transparency from 0 to 1.</p>
<p>.box-3 { background-color: rgba(#D13400, .6); }</p>
<p>would give an rgba color output.</p>
<h3 id="desaturate-%26-saturate" tabindex="-1">desaturate &amp; saturate</h3>
<p>These adjust the saturation (funnily enough) of the color by converting the hex value to HSL again. This like darkness and lighten requires a percentage to be passed.</p>
<p>.box-4 { background-color: saturate(#D13400, 40%); }
.box-5 { background-color: desaturate(#D13400, 40%); }</p>
<p>which gives more and less saturated colors respectively.</p>
<h3 id="complement-%26-invert" tabindex="-1">complement &amp; invert</h3>
<p>Here’s two I don’t think I’ve ever used. Again the hex colour is converted into HSL and then gets adjusted. For these you only pass the colour you’re wishing to adjust. No values or percentages.</p>
<p>.box-6 { background-color: complement($color); }
.box-7 { background-color: invert($color); }</p>
<p>would give the complementary and inverted color versions.</p>
<h3 id="adjust-hue" tabindex="-1">adjust-hue</h3>
<p>Another I can’t recall ever needing to use, again it converts the hex color value to HSL and requires a degree value(unit optional) being passed to calculate the adjustment.</p>
<p>.box-8 { background-color: adjust-hue($color, 40deg); }</p>
<p>gives a hue-adjusted color output.</p>
<h3 id="grayscale" tabindex="-1">grayscale</h3>
<p>I have never used this and struggle to figure out why one ever would, really. All the same, this (again) converts the hex to HSL creating a grayscale alternative to the color passed</p>
<p>.box-9 { background-color: grayscale($color); }</p>
<p>gives a grayscale version of the color.</p>
<h3 id="something%E2%80%99s-missing-(for-me)" tabindex="-1">Something’s missing (for me)</h3>
<p>I’ve dabbled with Compass. I don’t use it on any projects I work on as I quite like creating my own ‘things’ as much as Chris is doing a frickin’ fantastic job with it. There’s nothing I’ve missed not having when running with my own mixin library (yes, I know Compass does a (heck of a) lot more).</p>
<p>Two function I really liked in Compass that are native to Sass are tint &amp; shade. These work great for creating things like a <a href="http://www.stuffandnonsense.co.uk/archives/creating_colour_palettes.html">colour pallete</a>) so I use the following two functions to recreate what Compass gets tint and shade to do and have them in my mixin library ready to go.</p>
<p>Using the RGB mix function I can create the desired effect. Mix takes two colours and mixes them together with the given weight (percentage).</p>
<p>mix($color-1, $color-2, [$weight])</p>
<p>So if we used black and white for $color-1 we can create the tint and shade functions.</p>
<p>@function tint($color, $percent){
@return mix(white, $color, $percent);
}</p>
<p>@function shade($color, $percent){
@return mix(black, $color, $percent);
}</p>
<p>Which you would simply use like this.</p>
<p>.box-10 { background-color: tint($color, 40%); }
.box-11 { background-color: shade($color, 40%); }</p>
<p>which gives tinted and shaded color variations.</p>
<p>The tint and shade functions are found in my <a href="http://github.com/sturobson/Sassifaction/">Sassifaction</a> mixin library.</p>
<p>Like I said, I generally only use rgba, lighten, darken, tint and shade when I’m either having a play on codepen or when a project allows. It’s pretty nice and easy to only have to pass some simple information and get a hex value without having to worry about how it got there.</p>
<p>Go forth and colour yourself Sass-y.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>REMs, Fallbacks and Support</title>
      <link href="https://www.alwaystwisted.com/articles/rems-fallbacks-and-support.html"/>
      <updated>2014-01-01T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/rems-fallbacks-and-support.html</id>
      <content type="html">
        <![CDATA[
        <p>I’ve been using REMs for font sizing exclusively (with a fallback) since Jonathan <a href="http://www.twitter.com/snookca">Snook</a>’s article - <a href="http://snook.ca/archives/html_and_css/font-size-with-rem">font sizing with rem</a> from 2011. So I’ve been (more or less) writing out the font-size property like this.</p>
<p>.prose p {
font-size: 16px;
font-size: 1rem;
}</p>
<p>So, we’ve only got to <a href="http://caniuse.com/#search=rem">worry about supporting Internet Explorer 9 and up</a> as every modern browser in use today supports it, right? If we’re not wanting to support Internet Explorer 8 and below you could just do something like this and all the world will be happy.</p>
<p>.prose p {
font-size: 1rem;
}</p>
<p>Not necessarily. One browser that’s often missed is Opera mini.</p>
<p>Stop laughing. Here’s some numbers.</p>
<p>Tim Cook let the cat out of the bag and announced there were <a href="http://9to5mac.com/2013/10/22/tim-cook-talks-numbers-at-ipad-event-64-of-ios-devices-on-ios-7-20-million-itunes-radio-listeners-1-billion-songs-played/">170 million iPads</a> in the world. I’d quickly note that this doesn’t neccesarily mean that people are browsing the internet on those devices, but at a good guess let’s say they all are.</p>
<p>That’s a pretty big number but what’s that got to do with Opera mini?</p>
<p>Opera mini has <a href="http://www.operasoftware.com/smw/2013-11">241 million active users</a>.</p>
<p>That’s a pretty big number. Wait, that's 70 million more users than iPad owners.</p>
<p>So, if you’re going to be using REMs I think it’d be pretty wise to keep that pixel value fallback in there. I’m sure after you’ve gzip’d your CSS those additional characters will take up very little space.</p>
<h2 id="pre-processors" tabindex="-1">Pre-Processors</h2>
<p>The easiest and quickest way to always have that fallback set is using a pre-processor like <a href="#Sass">Sass</a>, <a href="#LESS">LESS</a> or <a href="#Stylus">Stylus</a>. Creating a mixin would mean you're writing less code meaning you're saving time for chocolates and such.</p>
<h3 id="less" tabindex="-1">LESS</h3>
<p>/* Set up a variable for maths */</p>
<p>@doc-font-size: 16;</p>
<p>/* the font-size mixin */</p>
<p>.font-size (@size) {
font-size: 0px + @size;
font-size: 0rem + @size / @doc-font-size;
}</p>
<p>/* example of usage */</p>
<p>.prose p {
.font-size(16);
}</p>
<p>/* example compiled */</p>
<p>.prose p {
font-size: 16px;
font-size: 1rem;
}</p>
<h3 id="sass(scss)" tabindex="-1">Sass(SCSS)</h3>
<p>/* Set up a variable for maths */</p>
<p>$doc-font-size: 16;</p>
<p>/* the font-size mixin */</p>
<p>@mixin font-size($size) {
font-size: 0px + $size;
font-size: 0rem + $size / $doc-font-size;
}</p>
<p>/* example of usage */</p>
<p>.prose p {
@include font-size(16);
}</p>
<p>/* example compiled */</p>
<p>.prose p {
font-size: 16px;
font-size: 1rem;
}</p>
<h3 id="stylus" tabindex="-1">Stylus</h3>
<p>/* Set up a variable for maths */</p>
<p>doc-font-size = 16</p>
<p>/* the font-size mixin */</p>
<p>font-size(size)
font-size: 0px + size
font-size: 0rem + (size / doc-font-size)</p>
<p>/* example of usage */</p>
<p>.prose p
font-size(16)</p>
<p>/* example compiled */</p>
<p>.prose p {
font-size: 16px;
font-size: 1rem;
}</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>2013</title>
      <link href="https://www.alwaystwisted.com/articles/2013.html"/>
      <updated>2014-01-01T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/2013.html</id>
      <content type="html">
        <![CDATA[
        <p>So, 2013 was my first year freelancing full time. I thought it’d be nice for me to just quickly jot some ‘statistics’ down from what’s happened since January 7th 2013.</p>
<p>Here goes...</p>
<p>This last year I’ve worked on 40 different projects. Ranging from some quick content updating of an HTML email, in both English and Welsh, to creating templates and WordPress sites.</p>
<p>With these 40 projects I’ve worked for 25 different clients. I think that’s quite a high number but it’s good to see that I’m retaining some regular clients for work now too. The start of 2014 sees me working one three projects for returning clients so hopefully it’s an upwards trend.</p>
<p>Unfortunately I’ve had two non-paying clients this year. Both were for reasonably small amounts (in my opinion) and have led me to tighten up my contract and ‘go with my gut’ rather than take any job going because I’d needed the money.</p>
<p>I’ve also had a stretch of 17 consecutive working days without any client work. It was at the start of the year and I noticed that I wasn’t ‘looking for the next gig’ as early as I’d needed to be and waiting until I’d finished one job before looking for another. This has been rectified and since July I think I’ve only had 2 consecutive days without work.</p>
<p>The shortest project took an hour to do. The longest lasted 13 working days.</p>
<p>I attended 9 conferences this year, 3 of which were online. I also attended 2 workshops and 4 evening events. I decided at the start of the year I was going to spend the first year going to as many as I could afford to and then reign myself in for 2014 and onwards. Looking at 2014 already, I don’t think that’s going to happen.</p>
<p>There’s probably some stuff I’ve missed. There’s a chance I’ll edit this post as I think upon it and add things.</p>
<p>Finally, come on 2014. Let’s be havin’ ya.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Not your average vertical rhythm Sass mixin</title>
      <link href="https://www.alwaystwisted.com/articles/not-your-average-vertical-rhythm-sass-mixin.html"/>
      <updated>2013-12-30T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/not-your-average-vertical-rhythm-sass-mixin.html</id>
      <content type="html">
        <![CDATA[
        <p>Way back when in September 2012 or so I was looking into vertical rhythm in design and layout. I instantly thought it would be great to create a Sass mixin that creates the line height and bottom margin for your typography based on the font size your pass it.</p>
<p>So I took to CodePen and created this -</p>
<p>// initial variables set-up
$doc-font-size:16;
$doc-line-height:24;
// mixin
@mixin font-size($size) {
font-size: 0px + $size;
font-size: 0rem + $size / $doc-font-size;
line-height: ceil($size / $doc-line-height) * ($doc-line-height / $size);
margin-bottom: 0px + $doc-line-height;
margin-bottom: ($doc-line-height / $doc-font-size) +rem;
}</p>
<p>This simple mixin gives the element the font-size in REM with PX fallback for OldIE and other browsers (like Opera mini). A line height based on the font-size and the document’s line height that’s set. Finally you get a bottom margin, again in REM with a PX fallback that’s defined by the documents font size and line height.</p>
<p>This gives you some sweet vertical rhythm for you site.</p>
<p>I had an itch.</p>
<p>What if I wanted an element to have no bottom margin? What if I wanted to have a bigger line-height or no line height or maybe a larger or smaller bottom margin?</p>
<p>So I took to codepen again and adapted that mixin to allow for those questions to be answered.</p>
<h3 id="so-where-is-it%3F" tabindex="-1">So where is it?</h3>
<p>It’s built in to my recently updated set of Sass mixins and files - <a href="https://github.com/sturobson/Sassifaction">Sassifaction</a>.</p>
<p>Therein it’s also built and ready in my Mixture Project - <a href="https://github.com/sturobson/Sassifaction-Mixture">Sassifaction Mixture</a>.</p>
<p>If you just want it on it’s own or have a play it’s also on <a href="http://codepen.io/sturobson/pen/fhige">CodePen</a>.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>How I write my Sass</title>
      <link href="https://www.alwaystwisted.com/articles/how-i-write-my-sass.html"/>
      <updated>2013-12-29T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/how-i-write-my-sass.html</id>
      <content type="html">
        <![CDATA[
        <p>Back at the beginning of May I added some ‘rules’ to how I write my Sass (or SCCS) on a <a href="http://github.com/sturobson/a-slightly-bizarre-starting-point">front-end project</a>.</p>
<p>I thought as I’ve just released version 2 of <a href="http://github.com/sturobson/Sassifaction">Sassifaction</a> I’d share my decisions in this blogpost to help clarify to myself how I should be writing my Sass and hopefully helping others make decisions on how they write their Sass and order things.</p>
<h2 id="at-the-beginning" tabindex="-1">At the beginning</h2>
<p>The follow short set of rules are part of my overall ‘guidelines’ inspired by and adapted from <a href="http://www.twitter.com/csswizardry">@CSSWizardry</a> and <a href="http://www.twitter.com/necolas">@necolas</a> amonst many others.</p>
<ul>
<li>Use tabs (4) over spaces.</li>
<li>Never go more than 3 levels deep.</li>
<li>Write the CSS in alphabetical order (for quick duplication checking).</li>
<li>Always a space after the properies colon.</li>
</ul>
<h3 id="the-beginning-comment" tabindex="-1">The Beginning Comment</h3>
<p>Each ‘lump’ of Sass should have a comment explaining what it is doing, what it is for and an example of the HTML that it’s being applied to. These are the only CSS comments to be found in any Sass document. This is so you can have a multi-line comment without needing to include the // every line.</p>
<p>/*</p>
<p>Header Element
============</p>
<p>This is the Sass for the header element layout for the project.</p>
<p><header role=”banner”></p>
<p></header>
*/</p>
<h3 id="starting-your-sass" tabindex="-1">Starting your Sass</h3>
<p>At the top of your block of Sass you should include any $variables, @mixins and @extends that are relevant to the element.</p>
<p>.module {
$main-color: #D13400;</p>
<p>@include remit(margin-bottom, 24);</p>
<p>@extend %btn;</p>
<p>}</p>
<p>As you can see each Sass specific item has an empty line underneath. There is also an empty line at the end of the block too.</p>
<h3 id="add-all-the-things" tabindex="-1">Add all the things</h3>
<p>After you’ve declared these bits of Sass you would then include any CSS that the element requires.</p>
<p>.module {
$main-color: #D13400;</p>
<p>@include remit(margin-bottom, 24);</p>
<p>@extend %btn;</p>
<p>background-color: $main-color:
border-radius: $radius-sml;
cursor: pointer;
padding: 0 3%;
width: 24%;</p>
<p>}</p>
<h3 id="pseudo-%26-combinator-selectors" tabindex="-1">Pseudo &amp; Combinator Selectors</h3>
<p>If the element we’re coding up has a pseudo selector or there is a combinator selector required these go after the block of CSS we’ve added.</p>
<p>.module {
$main-color: #D13400;</p>
<p>@include remit(margin-bottom, 24);</p>
<p>@extend %btn;</p>
<p>background-color: $main-color:
border-radius: $radius-sml;
cursor: pointer;
padding: 0 3%;
width: 24%;</p>
<p>&amp;:hover, &amp;:focus {
background-color: darken($main-color, 30%);
}</p>
<p>&amp; &gt; li {
font-weight: 700;
}</p>
<p>}</p>
<h3 id="nesting-elements" tabindex="-1">Nesting Elements</h3>
<p>If you need to nest elements (no more than 3 levels deep). Then you would add the nested elements at the end of the block with a space between each nesting.</p>
<p>.element {
background: blue;
display: block;
margin: 0 auto;
width: 44.15467%;</p>
<p>h1 {
color: green;
font-size: 32px;
font-size: 2rem;
}</p>
<p>.box {
width: 80%;
margin: 0 auto;
}</p>
<p>}</p>
<h3 id="nesting-media-queries" tabindex="-1">Nesting Media Queries</h3>
<p>All media queries are nested inline with the element rather than ‘at the end’.</p>
<p>.element {  background: red;
@media (min-width: 700px) {
background: blue;</p>
<p>}</p>
<p>}</p>
<h3 id="nesting-media-queries-with-nested-elements" tabindex="-1">Nesting Media Queries with Nested Elements</h3>
<p>Media Queries are placed at the end of the block after the pseudo and combinator selectors and any other nested elements. With a space separating them.</p>
<p>.element {
background: blue;
display: block;
margin: 0 auto;
width: 44.15467%;</p>
<p>h1 {
color: green;
font-size: 32px;
font-size: 2rem;
}</p>
<p>.box {
margin: 0 auto;
width: 80%;
}</p>
<p>@media (min-width: 700px) {
width: 100%;</p>
<p>h1 {
font-size: 48px;
font-size: 3rem;
}</p>
<p>.box {
width: 95%;</p>
<p>&amp; &gt; li {
margin-left: 2%;</p>
<p>}
}</p>
<p>}</p>
<p>}</p>
<h3 id="inline-commenting" tabindex="-1">Inline Commenting</h3>
<p>If you need to add a comment to part of a block of Sass then you would add a Sass comment (not a CSS comment) after the element.</p>
<p>.box {
margin-bottom: (2 * $doc-line-height); // bigs more space</p>
<p>}</p>
<h3 id="wrapping-up." tabindex="-1">Wrapping Up.</h3>
<p>This is how I structure my Sass at the moment. It’s an on going process of legibility and ease of use. As I’m generally the only person that will write the Sass/CSS for a project this works for me. I beseech you to take this and rip it apart, move bits, add bits and role your own and document it for you and/or your team.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Sass-y box-sizing fallback if needs must</title>
      <link href="https://www.alwaystwisted.com/articles/a-sass-y-box-sizing-fallback-if-needs-must.html"/>
      <updated>2013-12-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-sass-y-box-sizing-fallback-if-needs-must.html</id>
      <content type="html">
        <![CDATA[
        <p>I’ve recently had to create a dozen or so HTML templates for a client who’s sites audience has are keen fans of Internet Explorer 7 and use it regularly using the site.</p>
<p>With my irking toward modern front-end development and leaving the past to have a working, accessible site that might not look the same but all the content would still be there. Unfortunately on this occasion I couldn’t just give IE7 a linear single column of the site using something like Universal-IE7.</p>
<p>My main issue with the layout of the pages for this project is I’ve been using <code>box-sizing: border-box;</code> since last <a href="https://twitter.com/StuRobson/statuses/162674112991477761?tw_i=162674112991477761&amp;tw_e=details&amp;tw_p=archive">year</a>. Internet Explorer 7 and some (very old gecko and webkit browsers) don’t support this fantastic bit of CSS.</p>
<p>So I took to Codepen (it’s pretty much my first port of call for any HTML/CSS/JS thing I do) and started fleshing out a nice simple Sass mixin to create the compiled CSS for IE8 and up and then a different set of compiled CSS for IE7 and below.</p>
<h3 id="the-results" tabindex="-1">The Results</h3>
<p>I created a small little mixin that would allow you define a left and/or right padding as well as the width of the element. It would compile and create the width and padding for modern browsers and then create a set of CSS for IE7 at the same time adding a conditional comment. Currently you can set the widths in px or with percentages. I am trying to work out how to include ems for padding with a percentage width but haven’t got around to it yet. I just wanted to get this out there.</p>
<h3 id="so-where-is-it%3F" tabindex="-1">So where is it?</h3>
<p>It’s built in to my recently updated set of Sass mixins and files - <a href="https://github.com/sturobson/Sassifaction">Sassifaction</a>.</p>
<p>Therein it’s also built and ready in my Mixture Project - <a href="https://github.com/sturobson/Sassifaction-Mixture">Sassifaction Mixture</a>.</p>
<p>If you just want it on it’s own or have a play it’s also on <a href="http://codepen.io/sturobson/pen/uitIq">CodePen</a>.</p>
<h3 id="update%3A" tabindex="-1">Update:</h3>
<p>Thanks to the impecably dressed <a href="http://scottrileydesigns.co.uk/">Scott Riley</a> and a quick <a href="http://codepen.io/anon/pen/fraze">codepen</a> <a href="http://codepen.io/sturobson/pen/uGtEa">shuffle</a>, it's been updated and made a little cleaner</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Web Performance, the tools I use</title>
      <link href="https://www.alwaystwisted.com/articles/web-performance-the-tools-i-use.html"/>
      <updated>2013-12-19T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/web-performance-the-tools-i-use.html</id>
      <content type="html">
        <![CDATA[
        <p>Over the last 48 hours or so I've been asked a number of times about the tools I use when testing a sites performance. I thought it'd be frugal to have a link to point people at with a little explanation rather than a bombardment of 140 characters.</p>
<h3 id="web-page-test" tabindex="-1"><a href="http://www.webpagetest.org">Web Page Test</a></h3>
<p>This is the tool I often go to first. It allows you to enter an URL, decided where you want to test in the world and in what browser. This then tests the site (upto 9 times) and gives you several results to glean information from including a traffic light system of what you’re doing right, ok at or completely wrong.</p>
<h3 id="gtmetrix" tabindex="-1"><a href="http://gtmetrix.com/">GTMetrix</a></h3>
<p>This site combines two great tools into one nice package. Adding your URL runs the test through both Google’s PageSpeed and Yahoo’s YSlow resulting in a percentage score for both with pointers as to what needs doing in underneath. This is the tool I often tweet a screengrab from.</p>
<h3 id="mobitest" tabindex="-1"><a href="http://mobitest.akamai.com">Mobitest</a></h3>
<p>This is a great tool that just allows you to test a sites performance on a mobile device which is a great way to see how much data is being pushed to that pocket computer you've got in your hand.</p>
<p>These tools give you results in what you can do better most of which I’ve mentioned in <a href="../post.php%EF%B9%96s=2013-11-23-quick-wins-in-web-performance.html">a previous post</a>.</p>
<h3 id="recommended-reading" tabindex="-1">Recommended Reading</h3>
<p>If you’re really interested in web performance as a developer (and you really should be) then here’s a couple of books I’d highly recommend.</p>
<p>Web Performance by <a href="http://twitter.com/AndyDavies">Andy Davies</a> Available now as <a href="http://www.fivesimplesteps.com/products/web-performance">an eBook from Five Simple Steps</a></p>
<p>High Performance Browser Networking by <a href="http://twitter.com/igrigorik">Ilya Grigorik</a> Available freely <a href="http://chimera.labs.oreilly.com/books/1230000000545">online</a>, as an <a href="http://shop.oreilly.com/product/0636920028048.do">eBook</a> or a <a href="http://www.amazon.co.uk/High-Performance-Browser-Networking-performance/dp/1449344763">paperback</a></p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Using Mixture for client review</title>
      <link href="https://www.alwaystwisted.com/articles/using-mixture-for-client-review.html"/>
      <updated>2013-12-18T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/using-mixture-for-client-review.html</id>
      <content type="html">
        <![CDATA[
        <p>Most of the time I’m coding up ‘flat’ HTML for clients to then crack open and add to their CMS.</p>
<p>I’ve been using <a href="http://www.mixture.io">Mixture</a> for quite a time now (just over a year, where’s that time gone?) and I find the ability to host the work I’m doing on their servers as part of their monthly package fantastic.</p>
<p>Doing this means the client can see where I'm up to at anytime I push an update and also easily check it on their mobile or tablet device (or any device).</p>
<p>It’s also really good that it allows you to password protect the project if you wish to. Which is great for clients as there’s no chance someone else can happen upon the site and see what’s occurring, keeping any NDA intact.</p>
<p>I’d thought I’d share with you how I do this.</p>
<p>To make it easy for clients to remember the URL for their project to review I simply setup a redirect from my domain.</p>
<p>This way the client could (hopefully) easily remember myCompany.alwaystwisted.com rather than myCompany.alwaystwisted.mixture.io</p>
<p>A pretty simple ‘trick’ and a breeze to quickly set-up.</p>
<p>Of course, you could do this by just uploading the site to your server via FTP each time, but w/ Mixture it's one click and it's doing all that for you. Speedy.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Sass: An introduction. A workshop at Port80</title>
      <link href="https://www.alwaystwisted.com/articles/sass-an-introduction-a-workshop-at-port80.html"/>
      <updated>2013-12-18T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/sass-an-introduction-a-workshop-at-port80.html</id>
      <content type="html">
        <![CDATA[
        <p>I think <a href="http://port80events.co.uk/">Port80</a> was the first conference I went to where I thought. “I should be working in this industry full-time” rather than the night-owl work I was doing at the time.</p>
<p>Jump forward a short 19 months or so and I’m really happy to announce that at Port80 this next year (2014) I’m hosting a half-day workshop on an introduction to Sass.</p>
<p>One May 15th I’ll be presenting a workshop on Sass.</p>
<p>It’d be great to <a href="http://port80events.co.uk/event/port80-2014/">see you there</a>.</p>
<p>Get your tickets now from this <a href="http://port80events.co.uk/port80-workshops-in-may/">handy little link</a>.</p>
<h2 id="what-will-you-learn%3F" tabindex="-1">What will you learn?</h2>
<p>First we’ll look at CSS pre-processors, why and where you would use them, what they do and how they work. After this we’ll move onto how to use the power of Sass to make your CSS authoring more efficient and hopefully more fun.</p>
<h3 id="things-that-will-be-covered" tabindex="-1">Things that will be covered</h3>
<ul>
<li>Options for installing Sass on your machine</li>
<li>The two syntaxes, Sass &amp; SCSS</li>
<li>Variables, mixins and includes</li>
<li>Extends and placeholders</li>
<li>Built in functions</li>
<li>Media queries &amp; nesting</li>
<li>Compass, Bourbon and other frameworks</li>
<li>Sass and front-end performance</li>
<li>And more!</li>
</ul>
<h3 id="about-me" tabindex="-1">About me</h3>
<p>Stu Robson is a front-end developer from the deepest parts of Wiltshire, having been a night-owl freelancer for two years he took the jump into working full-time in January 2013. If he’s not coding he’s tweeting. If he’s not tweeting he’s usually spending time with his partner, Sarah and son, Ethan.</p>
<h3 id="additional-information" tabindex="-1">Additional information</h3>
<p>Please bring your laptop (hopefully with Sass installed) as this will in part be a practical workshop. Going through building a new project homepage using Sass.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Sass: An introduction. A workshop in Cardiff</title>
      <link href="https://www.alwaystwisted.com/articles/sass-an-introduction-a-workshop-in-cardiff.html"/>
      <updated>2013-12-13T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/sass-an-introduction-a-workshop-in-cardiff.html</id>
      <content type="html">
        <![CDATA[
        <p>I love what <a href="http://www.twitter.com/craiginwales">Craig</a> and <a href="http://twitter.com/amieduggan">Amie</a> have managed to achieve in such a short space of time. Spending an afternoon at <a href="http://foundershub.co.uk/">Founders Hub</a> I could see the passion and effort litterally beaming from every room.</p>
<p>It’s great that they’ve created something that in part gives something back to the community by just being there as an option for your office.</p>
<p>I’m a great believer in giving something back. I find this industry fantastic because of how happily everyone is in sharing what they learn more often than not for free.</p>
<p>Again, I digress. A few days after <a href="https://www.alwaystwisted.com/articles/handheldconf.com">Handheld Conference</a>, where the day before I attended a workshop at the Founders Hub Craig tweeted asking if there’s any interest in more workshops held at the venue. I quickly threw my cards on the table offering a half-day workshop to whoever wishes to attend (hopefully people interested in the subject).</p>
<p>So here we have it.</p>
<p>On January 8th at just gone noon I’ll be presenting a workshop on Sass.</p>
<p>If you're interested in attending I suggest you pop on over to <a href="http://foundershub.co.uk/calendar/intro-to-sass?view=calendar">this page at the Founders Hub website</a>.</p>
<p>update: all places for this have now been snapped up, which for me is kinda amazing. Looking forward to seeing you there.</p>
<h3 id="so-what's-being-discussed-in-this-workshop%3F" tabindex="-1">So what's being discussed in this workshop?</h3>
<p>A half-day workshop guiding you through the productivity-improving aspects of using the CSS pre-processor, Sass.</p>
<h2 id="what-will-you-learn%3F" tabindex="-1">What will you learn?</h2>
<p>First we’ll look at CSS pre-processors, why and where you would use them, what they do and how they work. After this we’ll move onto how to use the power of Sass to make your CSS authoring more efficient and hopefully more fun.</p>
<h3 id="things-that-will-be-covered" tabindex="-1">Things that will be covered</h3>
<ul>
<li>Options for installing Sass on your machine</li>
<li>The two syntaxes, Sass &amp; SCSS</li>
<li>Variables, mixins and includes</li>
<li>Extends and placeholders</li>
<li>Built in functions</li>
<li>Media queries &amp; nesting</li>
<li>Compass, Bourbon and other frameworks</li>
<li>Sass and front-end performance</li>
<li>And more!</li>
</ul>
<h3 id="about-me" tabindex="-1">About me</h3>
<p>Stu Robson is a front-end developer from the deepest parts of Wiltshire, having been a night-owl freelancer for two years he took the jump into working full-time in January 2013. If he’s not coding he’s tweeting. If he’s not tweeting he’s usually spending time with his partner, Sarah and son, Ethan.</p>
<h3 id="additional-information" tabindex="-1">Additional information</h3>
<p>This is more of a show and tell rather than a practical workshops. But please do bring your favourite laptop with you.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>What&#39;s in my bookmarks bar</title>
      <link href="https://www.alwaystwisted.com/articles/whats-in-my-bookmarks-bar.html"/>
      <updated>2013-11-25T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/whats-in-my-bookmarks-bar.html</id>
      <content type="html">
        <![CDATA[
        <p>I decided to spend some time this evening tidying up my bookmarks in Chrome.</p>
<p>Along with clearing out what I've bookmarked over the years I thought I'd tidy up my bookmarks bar as well.</p>
<p><img src="https://www.alwaystwisted.com/blog/bookmarks.png" alt="image of bookmarks bar" loading="lazy" decoding="async"></p>
<p>I save my bookmarks bar for predominantly handy JS bokmarklets. After tidying these up I thought it'd be something good to share.</p>
<p>So here goes...</p>
<p><a href="http://www.josscrowcroft.com/2011/code/window-size-bookmarklet/">Window Size Bookmarklet<br>
</a>A simple bookmarklet that gives a pixel value for the width and height of the browser viewport. As I convert px to em with Sass I find this easy and quick to understand</p>
<p><a href="https://gist.github.com/sturobson/6639967">New 'iPhone' Window<br>
</a>This opens what ever page you're on into a new window with reduced browser chrome to a size relative to an iPhone. This is good when using with Crhomes Dev Tools but I don't open it often anymore.</p>
<p><a href="https://gist.github.com/tzi/1607453">Print Preview<br>
</a>Without wasting paper until you really have to, here's a quick way to show how the page would look if printed.</p>
<p><a href="http://davatron5000.github.io/deCSS3/">deCSS3<br>
</a>From <a href="http://www.twitter.com/davatron5000">Dave Rupert</a>, this strips out any and all CSS3 so that you can have a quick look to make a guess at what older browsers would potentally render the page like.</p>
<p><a href="http://squizlabs.github.io/HTML_CodeSniffer/">HTML_codesniifer<br>
</a>A nice accessibility checker giving you a traffic light system of what's not right and how to fix it.</p>
<p><a href="http://www.benjaminkeen.com/open-source-projects/smaller-projects/responsive-design-bookmarklet/">RWD multiple pages<br>
</a>A bookmarklet that loads the current site into several mobile/tablet sizes iframes for quick checking. I don't open this one often.</p>
<p><a href="http://diagnosticss.github.io/">Diagnostic.css<br>
</a>This gives a visual indication of where your site would be inaccessible and where you have invalid markup.</p>
<p><a href="http://lab.maltewassermann.com/viewport-resizer/">Resizer<br>
</a>This gives you a little menu to makes the page your on resize to various preset viewport widths</p>
<p><a href="http://seesparkbox.com/foundry/media_query_bookmarklet">Media Query Bookmarklet<br>
</a>From the fine people of <a href="http://www.seesparkbox.com">Sparkbox</a> this gives you a ruler, it also outputs where your cursor is in X/Y but the beauty is that it shows you all the media queries being called at whatever size the browser is set at.</p>
<p>I've also got a bookmarklet for <a href="http://www.sassmeister.com">Sassmeister</a> and to create a new pen on <a href="http://www.codepen.io">CodePen</a> and that's it. Some handy little bookmarklets helping me make, test, break and fix websites every day.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Sass and Base64 images</title>
      <link href="https://www.alwaystwisted.com/articles/sass-and-base64-images.html"/>
      <updated>2013-11-23T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/sass-and-base64-images.html</id>
      <content type="html">
        <![CDATA[
        <p>Recently I was working on a client site with various triangular carat icons denoting if something was open or closed or whether it was a link. As the images were so small and after optimising them even small i thought I’d encode them in the CSS.</p>
<p>This got me thinking about how to use them with Sass.</p>
<p>Although I use Sass I still like a ‘tidy’ stylesheet before compiling. Adding Base64 encoded images gives me a chunk of text I don’t like the look of in my code. So it got me thinking.</p>
<h2 id="partials" tabindex="-1">Partials</h2>
<p>I had a cunning plan. Using a partial (_base64.scss) I thought I could add all my base64 images in there then, using a %placeholder for each one, I could @extend them in to my other stylesheet(s) where needed.</p>
<p>This worked perfectly. In my _base64.scss file I’ve got something similar to this -</p>
<p>%carat-triangle--up {
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAALCAYAAACzkJeoAAAAVklEQVQY02N4+uzNVCBmY8AGgBL/gfg4EEvjkgThl0DsiEsShH8DcSkQM2KThOE1QMyHSxKEN+GSXI9N5x8grsRm5ysgdsbm2pNALIfNn9OBmB1bAAEAjTeww9HNXe8AAAAASUVORK5CYII=);
}</p>
<p>To which I then included it into something like this -</p>
<p>.error-message {
// code for error message
&amp;:before {
@extend %carat-triangle--up
// code for included this icon
}
}</p>
<p>Using %placeholder and @extend means I can call the the icon what it is, clearly and concisely. Where as in the compiled CSS file it might be part of the .error-message I would easily be able to tell from the @extend that what it looks like, a %carat-triangle--up.</p>
<p>Now I’ve got some nice icons in the stylesheet saving on HTTP requests but I don’t see them as they’re (to me) hidden away when working on my Sass files.</p>
<h2 id="compass" tabindex="-1">Compass</h2>
<p>If you’re using <a href="http://compass-style.org/">Compass</a>, you can forgo having to create the Base64 images by letting the framework <a href="http://compass-style.org/reference/compass/helpers/inline-data/#inline-image">do the work for you</a>. Including the image you want to be a data-uri like this -</p>
<p>background-image:  inline-image(‘carat-open.png’);</p>
<p>When compiled will create the Base64 code for you. So you might not even need a separate partial.</p>
<h2 id="mixture" tabindex="-1">Mixture</h2>
<p>The guys at <a href="http://mixture.io/">Mixture</a> are awesome. I mentioned this feature to them a while ago and within 48 hours it was <a href="http://docs.mixture.io/preprocessors#base">in the app</a>. So if you use Sass, LESS or Stylus you can do the same thing using this code -</p>
<p>background-image: inline-image('carat-open.png');</p>
<p>Will also output the Base64 code when Mixture compiles.</p>
<h2 id="base64-encoded-files" tabindex="-1">Base64 encoded files</h2>
<p>If you’re supporting modern browsers (IE8+) then you’d be easily able to include Base64 images into your compiled CSS file. Note that Base64 encoding adds about 25-30% to the file size of the original image file size so don’t use it for everything. Personally, I never encode anything that’s larger than 4kb as an image.</p>
<h2 id="performance" tabindex="-1">Performance</h2>
<p>They’re have been <a href="http://www.mobify.com/blog/data-uris-are-slow-on-mobile/">several</a> <a href="http://www.mobify.com/blog/base64-does-not-impact-data-uri-performance/">recent</a> <a href="http://java-performance.info/base64-encoding-and-decoding-performance/">posts</a> about the performance of using Base64 encoded files over using actual images. There is no silver bullet. The best thing to do is test both early and see which will be the best way to go.</p>
<p>This helps me, a tidy set of Sass partials is a tidy mind, hiding the ‘random’ collection of letters and numbers or even the files I’m importing just helps me build my projects out.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>quick wins in web performance</title>
      <link href="https://www.alwaystwisted.com/articles/quick-wins-in-web-performance.html"/>
      <updated>2013-11-23T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/quick-wins-in-web-performance.html</id>
      <content type="html">
        <![CDATA[
        <p>Following on from a workshop by <a href="https://twitter.com/andydavies">Andy Davies</a> I attended at <a href="http://port80events.co.uk/">Port80</a> this year I am forever looking at how newly launched sites perform. Most of them, invariably, have things that could do with tightening up, making the overall file size smaller and making them download and run quicker.</p>
<p>Running your site through something like <a href="http://www.webpagetest.org">webpagetest.org</a> or <a href="http://www.gtmetrix.com">gtmetrix.com</a> will help show you (through their summary pages) where you could improve your sites performance by pointing out where it’s currently failing.</p>
<p>Below are some ‘quick wins’. Some easy things to do to make your sites better, smaller and more performant.</p>
<h2 id="image-optimisation" tabindex="-1">Image Optimisation</h2>
<p>Optimising images is something that’s quite easy to do but it’s also something that’s often missed. They’re also, more generally, the biggest part of a web page in terms of file size. There are a couple of ways that we can help reduce a web pages file size and performance by doing some simple things.</p>
<p>Are you using the correct file format? It’s easy to export a photo as a PNG24 in Photoshop but wouldn’t it be better as a jpg? Would it be better to use an SVG instead of some gifs for your social media icons. Thinking about what the file type is you’re actually needing will help reduce the file size before you’ve left Photoshop.</p>
<p>Once you’ve got the correct file format are they as optimised as possible. You can only do so much with Firework or Photoshop. You’ll need to use a compression tool like <a href="http://imageoptim.com/">imageoptim</a>(lossless compression), <a href="https://www.alwaystwisted.com/articles/jpegmini.com">jpegmini</a>(lossy compression), <a href="https://github.com/svg/svgo">SVGO</a>(for compressing SVG files) or something integrated in an application that’ll squeeze the kilobytes out of the files even more again reducing the over file size of the page.</p>
<p>If there are several icons on the site you’re building. Rather than give each one a separate file which you would call in the CSS (for example) create a sprite sheet. Making only one file of several files helps reduce the calls to the server for the image required.</p>
<h2 id="removing-duplication-and-cruft" tabindex="-1">Removing Duplication and Cruft</h2>
<p>As mentioned in a <a href="../post.php%EF%B9%96s=2013-11-11-case-study-the-up-group-website-performance.html">previous blogpost</a> I wrote how I made a quick win by spotting duplicate code for Google analytics. Going through your site and removing any duplication you find will be a very quick win.</p>
<p>As well as duplicate code, there may be code that started out being used in the project but is now redundant. Removing any of this redundant code (with something like <a href="https://github.com/giakki/uncss">UnCSS</a>) will help reduce your file size.</p>
<h2 id="bad-requests" tabindex="-1">Bad Requests</h2>
<p>We’re all human, sometimes we mistype things, sometimes we forget to delete references to things we’ve deleted. Looking at what gets downloaded by your browser will tell you if, somewhere in the page, you’re referencing something that doen’t exist.</p>
<p>Browsers are triers. If it fails to find something you’ve included, an image or font file for example, it will continue to look for it just in case it itself failed on the first time to grab it from the server. If this was a font then your sites visitor could be faced with a page with no text for some time. Checking this whilst in development and before you push live will help stop this happening.</p>
<h2 id="putting-your-javascript-at-the-end-of-the-document" tabindex="-1">Putting your JavaScript at the end of the document</h2>
<p>Putting as much JavaScript at the bottom of the page defers the loading of that JS. JavaScript at the top of the document in the</p>
<p>will block the page rendering giving the sites visitor a blank page until it’s finished loading. Putting it at the bottom will help this as the page will render the HTML and CSS without being blocked.</p>
<h2 id="reducing-http-requests" tabindex="-1">Reducing HTTP requests</h2>
<h3 id="css" tabindex="-1">CSS</h3>
<p>You don’t need a separate file for your reset. Your print stylesheet is so small you can add it the end. You really only need to send one CSS file down the pipe.</p>
<p>Now with responsive web design you might have a mobile, tablet and desktop CSS file. You really don’t need to split them up. One file to rule them all. Cuts down the amount of HTTP requests meaning your page might actually perform a little bit better.</p>
<p>For this a pre-processor really helps. You can easily import all of your Sass/LESS/Stylus files into one so when it compiles you get one gorgeous CSS file. That way you can still have the separate ‘bits’ of CSS to code but have one file on the server. Doing this with just CSS you just have one file and write all of your CSS in that one file.</p>
<h3 id="js" tabindex="-1">JS</h3>
<p>You could do the same for your JS. I don’t I like to keep certain bits in their own file. If I use jQuery it gets its own file with its own HTTP request as do <a href="https://www.alwaystwisted.com/articles/modernizr.com">Modernizr</a> and Google Analytics.</p>
<p>Where I do concatenate and conjoin files is to keep any ‘plugin’ Javascript in one file ‘plugins.js’ and one for any other code ‘scripts.js’. So if you’ve got a plugin for a mobile menu, a slider, a back-to-top button. Rather than 3 files that would all go into the plugins.js file.</p>
<h2 id="minification" tabindex="-1">Minification</h2>
<h3 id="html" tabindex="-1">HTML</h3>
<p>If you wanted to you could minify the HTML of your webpages. To be honest I’ve never done this. I’m sure if you quickly google you’ll be able to find something that’d do this but when you bring in the various CMSs available today for me it’s just easier to leave it as it is. Remove your comments though doesn’t need to be there in your production code.</p>
<h3 id="css-1" tabindex="-1">CSS</h3>
<p>When you’re writing CSS I’m sure, like me, you want to be able to quickly understand what each bits doing, adding comments so you can easily scan and find the relevant CSS you need to edit.</p>
<p>The browser doesn’t care about readability. It doesn’t matter how you’ve nicely laid out your CSS and what comments you’ve added. A quick win here would be to minify the CSS you’ve concatenated so that it strips out and whitespace and any comments you’ve added. This will shave down the kilobytes being pulled down the pipe meaning a faster download.</p>
<p>If you use a pre-processor then you can easily add all the comments you want in the world and then minify the outputted CSS when compiling. There are several apps that allow you to do this for LESS, Stylus and Sass. If you’re still writing CSS without one of these you can still minify the CSS from various applications.</p>
<h3 id="javascript" tabindex="-1">JavaScript</h3>
<p>Minifying your JavaScript is something to do for the same reasons as previously mentioned. The browser won’t care and it’ll save you a little overall file size.</p>
<h2 id="gzip" tabindex="-1">Gzip</h2>
<p>Gzip’ing takes your minified CSS and JavaScript and squeezes even more from it. Squeezing the file size again means a smaller overall page size meaning, potentially, a quicker download. For example, if you were to minify and then GZip jQuery you could reduce the size to around 22% of its original uncompressed file size.</p>
<p>To enable this you must be able to access the server as you’d need to edit (or create) the .htaccess file and add this code -</p>
<p>#Gzip
<ifmodule mod_deflate.c>
AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript text/javascript
</ifmodule>
#End Gzip</p>
<h2 id="adding-expires" tabindex="-1">Adding Expires</h2>
<p>Chances are when the site goes live it’s CSS file won’t change that often. The Javascript file, logo and social media icons also might not change until the next redesign/realign. Adding expires or a cache-control header to the .htaccess file can stop the browser from downloading files unless it needs to. Caching what you tell it so the next time the visitor comes to the site, hopefully, they’ll get the page faster than the first time.</p>
<p>You could add this (taken from the <a href="https://github.com/h5bp/html5-boilerplate/blob/master/.htaccess">HTML5 Boilerplate</a>)</p>
<p><IfModule mod_expires.c>
ExpiresActive on</p>
<p># Perhaps better to whitelist expires rules? Perhaps.
ExpiresDefault                          'access plus 1 month'</p>
<p># cache.appcache needs re-requests in FF 3.6 (thx Remy ~Introducing HTML5)
ExpiresByType text/cache-manifest       'access plus 0 seconds'</p>
<p># Your document html
ExpiresByType text/html                 'access plus 0 seconds'</p>
<p># Data
ExpiresByType text/xml                  'access plus 0 seconds'
ExpiresByType application/xml           'access plus 0 seconds'
ExpiresByType application/json          'access plus 0 seconds'</p>
<p># RSS feed
ExpiresByType application/rss+xml       'access plus 1 hour'</p>
<p># Favicon (cannot be renamed)
ExpiresByType image/x-icon              'access plus 1 week'</p>
<p># Media: images, video, audio
ExpiresByType image/gif                 'access plus 1 month'
ExpiresByType image/png                 'access plus 1 month'
ExpiresByType image/jpg                 'access plus 1 month'
ExpiresByType image/jpeg                'access plus 1 month'
ExpiresByType video/ogg                 'access plus 1 month'
ExpiresByType audio/ogg                 'access plus 1 month'
ExpiresByType video/mp4                 'access plus 1 month'
ExpiresByType video/webm                'access plus 1 month'</p>
<p># HTC files  (css3pie)
ExpiresByType text/x-component          'access plus 1 month'</p>
<p># Webfonts
ExpiresByType font/truetype             'access plus 1 month'
ExpiresByType font/opentype             'access plus 1 month'
ExpiresByType application/x-font-woff   'access plus 1 month'
ExpiresByType image/svg+xml             'access plus 1 month'
ExpiresByType application/vnd.ms-fontobject 'access plus 1 month'</p>
<p># CSS and JavaScript
ExpiresByType text/css                  'access plus 1 year'
ExpiresByType application/javascript    'access plus 1 year'
ExpiresByType text/javascript           'access plus 1 year'</p>
<p><IfModule mod_headers.c>
Header append Cache-Control 'public'
</IfModule></p>
<p></IfModule></p>
<p>The browser will cache and keep the files for as long as specified, if possible. I say if possible because every browser has a different amount of ‘space’ for caching. On a mobile browser it’s even less so. Doing this helps to possibly speed up future visits and that’s worth doing I reckon.</p>
<h2 id="applications" tabindex="-1">Applications</h2>
<h3 id="less%2C-sass%2C-stylus" tabindex="-1">LESS, Sass, Stylus</h3>
<ul>
<li><a href="https://www.alwaystwisted.com/articles/mixture.io">Mixture</a> (OSX/Win)</li>
<li><a href="https://www.alwaystwisted.com/articles/incident57.com/codekit">Codekit</a> (OSX)</li>
<li><a href="http://alphapixels.com/prepros/">Prepos</a> (OSX/Win)</li>
</ul>
<h3 id="less" tabindex="-1">LESS</h3>
<ul>
<li><a href="http://incident57.com/less/">LESS.app</a> (OSX)- hasn’t been updated since March 2013</li>
</ul>
<h3 id="sass" tabindex="-1">Sass</h3>
<ul>
<li><a href="http://mhs.github.io/scout-app/">Scout</a> (OSX/Win)</li>
<li><a href="http://compass.kkbox.com/">Compass.app</a> (OSX/Win)</li>
<li>Command Line</li>
</ul>
<h3 id="other" tabindex="-1">Other</h3>
<ul>
<li><a href="http://procssor.com/">Procssor</a> (OSX)</li>
</ul>
<h3 id="web-based" tabindex="-1">Web-based</h3>
<ul>
<li><a href="http://procssor.com/">Procssor</a></li>
<li><a href="http://www.jsmini.com">jsmini.com</a></li>
<li><a href="http://marijnhaverbeke.nl/uglifyjs">uglify</a></li>
</ul>
<h2 id="recap" tabindex="-1">Recap</h2>
<p>Hopefully this has helped put fire in your belly. Making your site as lean as possible is not only good for your visitors, it's also good for your server costs. Smaller file sizes and less file means less storage space required and less bandwidth needed for the site to be accessed.</p>
<p>Everyone's a winner baby, that's the truth</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Case Study: The Up Group Website Performance</title>
      <link href="https://www.alwaystwisted.com/articles/case-study-the-up-group-website-performance.html"/>
      <updated>2013-11-11T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/case-study-the-up-group-website-performance.html</id>
      <content type="html">
        <![CDATA[
        <p>I was recently contacted by Manne from The Up Group. He wanted me to take a look at their site (built on ModX) to see what was making the site (and it’s homepage predominantly) load slowly and what could be done to improve the performance of their website <a href="http://www.theupgroup.com">www.theupgroup.com</a>.</p>
<h2 id="preliminary-review" tabindex="-1">Preliminary Review</h2>
<p>Before moving straight into the codebase to see what I could glean from it I ran several tests to using some web page performance applications.</p>
<p>The tools I used were Google’s PageSpeed Chrome <a href="https://developers.google.com/speed/pagespeed/">DevTools extension</a>, a test on <a href="https://www.alwaystwisted.com/articles/webpagetest.org">WebPageTest</a> and a test on <a href="http://gtmetrix.com/">GTMetrix</a>.</p>
<p>The initial resulting score from GTMetrix was -</p>
<p><img src="https://www.alwaystwisted.com/blog/UpGroupBEFORE.gif" alt="UpGroup Performance Statistics Before" loading="lazy" decoding="async"></p>
<p>On average it took the sites homepage 4.3 seconds to download and have a time to first byte at a very slow average of 2.4 seconds so was lots of room for improvement.</p>
<p>In the review I noted that to improve the pages download speed and time there was oppurtunity to reduce HTTP requests, make the CSS and JavaScript filesizes smaller, removing anything that’s no longer needed and optimising the images used.</p>
<h2 id="asset-location-and-http-requests" tabindex="-1">Asset location and HTTP requests</h2>
<p>Looking at the HTML the JavaScript was being called at the top of the page. This was blocking the rest of the page from being loaded (the HTML at minimum) whilst the JavaScript had downloaded and run.</p>
<p>There were also 5 separate JavaScript files being called as well as 3 different CSS files being called on the page. Concatenating these into fewer HTTP requests would mean the site isn’t having to connect to the server more times than it needs to to load the page.</p>
<h2 id="duplication-of-file-requests" tabindex="-1">Duplication of file requests</h2>
<p>Going through the page I noticed there were two calls to the favicon.ico and also two calls to the Google Analytics code. Removing these reduced two unneeded HTTP request. A nice and simple quick win.</p>
<h2 id="minify-%26-gzip" tabindex="-1">Minify &amp; GZip</h2>
<p>With the JavaScript and CSS now taking fewer HTTP request to get to the browser it was time to look out squashing every byte out to make them as small as possible.</p>
<p>To that end minifying both the CSS and JS files gave a saving of around 80kb on the total page weight.</p>
<p>I also edited the .htaccess file to GZip the JavaScript and CSS files to reduce the file sizes a little bit more too.</p>
<h2 id="image-optimisation" tabindex="-1">Image Optimisation</h2>
<p>The site has a logo and two social icons in the header, on the homepage there is a black and white image of a man hold the company ident as well as 20 logos from companies that The Up Group has worked with. I used <a href="http://imageoptim.com/">ImageOptim</a> to squeeze the file size of the site logo, icons and ‘man’ as well as the group of logos used.</p>
<p>For the logos I also put them into one image sprite sheet and used CSS to save 19 separate HTTP requests for the page.</p>
<h2 id="caching" tabindex="-1">Caching</h2>
<p>Once all these were done I went back to the .htaccess file to extend the caching period of the files so that the browser would keep them in the hope the next time the visitor goes to the site they wouldn’t have to download everything all over again.</p>
<h2 id="improvements" tabindex="-1">Improvements</h2>
<p>In doing all these things above I then ran the site through the tests above again and found that there was a significant improvement. Both the download time and the time to first byte were improved as were the scores -</p>
<p><img src="https://www.alwaystwisted.com/blog/UpGroupBEFORE-AFTER.gif" alt="UpGroup Site Performance After" loading="lazy" decoding="async"></p>
<p>I don’t think that’s a bad effort for around a days work. I also gave the sites homepage a facelift, but I’ll keep that for another blogpost.</p>
<p><a href="http://www.theupgroup.com"><img src="https://www.alwaystwisted.com/blog/UpGroupHomePage.jpg" alt="UpGroup Redesign" loading="lazy" decoding="async"></a></p>
<p>(note: the site has had a complete redesign by others since I did this work. The results may vary differently if you tested now).</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Deciding in the Browsers</title>
      <link href="https://www.alwaystwisted.com/articles/deciding-in-the-browsers.html"/>
      <updated>2013-09-03T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/deciding-in-the-browsers.html</id>
      <content type="html">
        <![CDATA[
        <p>Just a thought. Now that some web designers and developers are moving to ‘designing in the browser’ are we unintentionally boxing ourselves by doing so? Are designers now mainly designing in one browser at different sizes.</p>
<p>I hope not. That does not really work.</p>
<h3 id="time-flies" tabindex="-1">Time Flies</h3>
<p>I really cannot believe it was 2008 when Andy Clarke proposed the idea of designing in the browser. I guess it’s because it’s being reiterated in many forms that it just seems like a fresh idea still.</p>
<p>Although there are many posts, talks, interviews about how we should all be designing in the browser there are no rules and if you cannot design purely in the browser that’s not a problem.</p>
<p>It’s not binary.</p>
<h3 id="%E2%80%9Cdeciding-in-the-browser%E2%80%9D" tabindex="-1">“Deciding in the browser”</h3>
<p>The phrase reimagined by Dan Mall in September 2012 shows the progression of thought around the idea. I think it needs changing. Ever so slightly. “Browser” to me just screams ‘one thing’. If we made this ‘browsers’ I’d be happier. This, to me, means more than resizing your chrome window.</p>
<h3 id="i-saw-a-site-today%2C-oh-boy." tabindex="-1">I saw a site today, Oh boy.</h3>
<p>So this is all spurred on from a recent designers new site being launched. If you know me, you’ll know I’m pretty much on twitter 24/7. Consequently I’d say 98% of all links I click are opened in Chrome iOS rather than Chrome on my Air.</p>
<p>So clicking a link I was presented with a readability nightmare. 3/4 words per line of text and huge amount of margin either side of the text. Without getting my Gridset ruler out I would guess at 80 pixels of my 320 pixels was made up of white space. 25% of a small screen is quite large.</p>
<p>Checking the site on my Air though, at 320 pixels wide, and it looked nice. The margin didn’t seem so huge. It worked.</p>
<p>This’d be where, possibly, deciding in just the one browser isn’t a great idea. You need to decide, design and test on anything you’ve got to hand to make the best device-agnostic site you can.</p>
<p>So, let’s call it ‘deciding in the browsers’ whether we start with Photoshop or HTML/CSS. Just don’t restrict yourself to one browser.</p>
<p>Okay?</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Why not write a book?</title>
      <link href="https://www.alwaystwisted.com/articles/why-not-write-a-book.html"/>
      <updated>2013-08-25T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/why-not-write-a-book.html</id>
      <content type="html">
        <![CDATA[
        <p>Ok. So I'm thinking of writing a book.</p>
<blockquote>
<p>'Everybody does have a book in them, but in most cases that's where it should stay.'</p>
<p>Christopher Hitchens</p>
</blockquote>
<p>It's (at this moment) titled – 'Modern Front-End Development Using Sass'.</p>
<p>I'm hoping to take people through the processes of setting up and using Sass to create beutifully maintainable front-end code. It's not all about Sass though, it's also about developing your own boilerplate. Something I'm very passionate about. With the importance of having code that anyone can understand by creating your own 'guidelines' and also ways that your maintainable code should be as performant as possible.</p>
<p>The idea is in its gestation period at the moment. Who knows, bear with me.</p>
<p>Let's see how this goes. It might go a bit '<a href="http://www.urbandictionary.com/define.php?term=it's%20all%20gone%20pete%20tong">Pete Tong</a>' but hopefully not.</p>
<p>If you're interested in this, a comment would be greatly appreciated.</p>
<p>Thanks,</p>
<p>S</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Look Ma, I&#39;m on the telly!</title>
      <link href="https://www.alwaystwisted.com/articles/look-ma-im-on-the-telly.html"/>
      <updated>2013-08-23T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/look-ma-im-on-the-telly.html</id>
      <content type="html">
        <![CDATA[
        <p>Ok, so not totally true.</p>
<p>In July I was more than happy to talk to a bunch of like minded fellows at an event held the Mozilla space in London. The event was organised by my two good friend <a href="http://www.twitter.com/mrqwest">Anthony</a> and <a href="http://www.twitter.com/onishiweb">Adam</a> masterminds behind <a href="http://12devs.co.uk/">12Devs</a>. This was there third foray into evening mini-conferences after having two great years of collating articles for the 12 days following Christmas Day.</p>
<p>I'm someone that's said they'd never talk publicly. I'm slightly introvert (unless you add lager) and suffer serious bouts of imposter syndrome. For 5 years, on and off, I was in a band and you'd forever see the back of my head when we played live. The limelight was/is something that I'm not really too fussed about. As it were.</p>
<h2 id="but-i-digress..." tabindex="-1">But I Digress...</h2>
<p>However, having talked with Ant. about 12 Devs of Easter I happened upon a subject that I thought needed airing in public. I've not really taken a shine to the myriad of boilerplates, frameworks and starting points that are oozing out of the sides of this industry. The beauty of HTML/CSS in particular is you can have your own 'style' of coding and you can decide what to have and not have in your documents. In my talk I touched upon this plus other stuff. Believing that the best boilerplate is the one you write yourself. Where you borrow code from the many and adapt it so it suits how you 'write code'.</p>
<p>Sweating the details of what's in your stock HTML template or how your write your CSS (well, Sass) makes you make your code delicous.</p>
<h2 id="without-further-ado..." tabindex="-1">Without Further Ado...</h2>
<p>Here's the video</p>
<h2 id="more-than-just-me" tabindex="-1">More than just me</h2>
<p>I'd like to thank Adam and Anthony for letting me 'try my hand at this. Will I do this again? Maybe, but I'd probably have one less beer.</p>
<p>For the other talks of the evening, head over to the <a href="http://12devs.co.uk/summer-videos/">12 Devs Of Summer vide page</a>.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Bugs, Browsers and Bookmarklets</title>
      <link href="https://www.alwaystwisted.com/articles/bugs-browsers-and-bookmarklets.html"/>
      <updated>2013-07-02T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/bugs-browsers-and-bookmarklets.html</id>
      <content type="html">
        <![CDATA[
        <p>update: Opera Next 16 fixes the ability to open a document.</p>
<p>I was watching the <a href="http://vimeo.com/69386528">'hot topics' panel discussion</a> from Mobilism yesterday where that <a href="http://www.adactio.com">Jeremy Keith</a> was regaling a story he had with an Apple devrel who said they read <a href="http://adactio.com/journal/4470/">blogposts</a> about bugs. So after the public launch of <a href="http://my.opera.com/ODIN/blog/2013/07/02/introducing-opera-15-for-desktop-and-a-fast-release-cycle">Opera 15</a>, here goes mine.</p>
<p>I've always, sort of, been a fan of clean UI of Opera but due to all the cool kids and their webkits up until Opera Next was released with Blink I stuck with Chrome and after however many days it's been I haven't really touched Chrome at all.</p>
<p>Every transition will never run as smoothly as you'd want it too. I miss my bookmarks, quite a bit. In chrome I've got a couple set up for development that I just can't darg and drop into Chrome (on research today though I think I can create my own 'extensions' for them. I'll release them if I can).</p>
<p>With any development release you should expect bugs. I found 3 or 4 and submitted them to <a href="https://bugs.opera.com/wizarddesktop/">Opera's bug tracker</a>. Here lies one problem. I don't know if I'm repeating someone elses bug report. As Opera (thus far) have chosen to have a closed doors tracking system you can't see if your bugs filed already, if someone's looking at  it, fixing it or if it's been closed. That's pretty crappy in 2013. I really hope Opera open this up, and fast.</p>
<p>As they don't have an out in the open tracking system I can't see if a bug I reported in Next which has made it through to public has been looked at or not, whether it's closed or not or what the hell they're doing about it.</p>
<p>I think the bug is pretty big. I can't open a file. [cmd] O or via the menu is just not working in the current public or next release on OS X. I think that's quite a big bug that needs squashing. So in light of today's release and listening to Jeremy on tape yesterday, I hope the developers find this post (I'll link them to it) and get this bug squashed.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Smarter RGBa fallbacks with Sass</title>
      <link href="https://www.alwaystwisted.com/articles/smarter-rgba-fallbacks-with-sass.html"/>
      <updated>2013-05-06T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/smarter-rgba-fallbacks-with-sass.html</id>
      <content type="html">
        <![CDATA[
        <p>I've been working on a client site that's been making great use of colourful transparent colours for defining the main categories of their resources. The development spec also required support for Internet Explorer 8 and as we know, RGBa isn't supported so I needed a fallback.</p>
<h2 id="currently" tabindex="-1">Currently</h2>
<p>Looking at current suggestions or 'best practices' for using RGBa with a fallback for older browsers gives us the idea to use the block colour used for the RGBa as a back up, like this -</p>
<p>.element {
color: #FF0000;
color: rgba(255, 0, 0, 0.5);
}</p>
<p>I think that, although it's an acceptable answer, it's pretty crappy. You site visitors would get something that looks good on their older browser still. Wouldn't it be better to offer them a fallback colour that's closer to the transparent colour?</p>
<h2 id="colouring-function" tabindex="-1">Colouring Function</h2>
<p>So I took to codepen to thrash out a little bit of Sass which gives you the transparent colour with a (close as possible without hand coding) fallback.</p>
<p>I say it's close as possible because the transparent colour will react differently to a lighter or darker background but using a closer fallback, I think, is better than just the non-transparent colour.</p>
<p>After some playing with some code I worked out roughly what numbers I needed for both and I came to this function -</p>
<p>@function trans($color, $percentage) {
@if $percentage == .1 {
@return lighten($color, 45%);
}
@if $percentage == .2 {
@return lighten($color, 40%);
}
@if $percentage == .3 {
@return lighten($color, 35%);
}
@if $percentage == .4 {
@return lighten($color, 30%);
}
@if $percentage == .5 {
@return lighten($color, 25%);
}
@if $percentage == .6 {
@return lighten($color, 20%);
}
@if $percentage == .7 {
@return lighten($color, 15%);
}
@if $percentage == .8 {
@return lighten($color, 10%);
}
@if $percentage == .9 {
@return lighten($color, 5%);
}
}</p>
<p>This recreates a fallback colour estimated from the percentage of colour you're wanting for your transparent image where $color is the hexadecimal colour and $percentage is the a of RGBa.</p>
<h2 id="mixin-it-up" tabindex="-1">Mixin it up</h2>
<p>To get this to work I needed a little mixin to use the function when I'm needing a transparent background color or text color. So I made this for it -</p>
<p>@mixin tran($type, $color, $percentage) {
@if $type == color {
color: trans($color, $percentage);
color: rgba($color, $percentage);
}
@if $type == bg {
background-color: trans($color, $percentage);
background-color: rgba($color, $percentage);
}
}</p>
<p>Going through this we would need to define a $type, be it a background-color(bg) or just a color(color). The hexadecimal colour($color) and the level of tranparency($percentage). We could then include it in our Sass(SCSS) code like this -</p>
<p>header {
@include tran(bg, #00ff00, .8);
}</p>
<p>Which would gives us this resulting CSS -</p>
<p>header {
background-color: #33ff33;
background-color: rgba(0, 255, 0, 0.8);
}</p>
<p>Where the fallback colour is a lot closer to the RGBa than #00FF00 would be.</p>
<h2 id="close-but-no-cigar" tabindex="-1">Close but no cigar</h2>
<p>This bit of Sass(SCSS) gives us a 'close as possible' fallback. As the colour of a transparent element will change depending on the dark or light colours behind it. It's not perfect but it gives a closer fallback for your designs.</p>
<p>This is available now on <a href="http://codepen.io/sturobson/pen/cbusa">codepen to grab</a> and also now included in my Sass library <a href="https://github.com/sturobson/sassifaction">Sassifaction</a></p>
<h2 id="update---the-great-internet" tabindex="-1">UPDATE - The great internet</h2>
<p>So some hours have passed and <a href="http://twitter.com/@japborst">@japborst</a> has just submitted a lovely pull request to update the code and remove all of the @if statements. The code to get it to work for the function is now -</p>
<p>@function trans($color, $percentage, $shade) {
@return lighten($color, (1-$percentage)*5%);
}</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Sassifaction in Colour Palette Mixins</title>
      <link href="https://www.alwaystwisted.com/articles/sassifaction-in-colour-palette-mixins.html"/>
      <updated>2013-04-07T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/sassifaction-in-colour-palette-mixins.html</id>
      <content type="html">
        <![CDATA[
        <p>When I used to design sites as well as develop them. There was one blogpost that really helped me with my final colour choices. This was Andy Clarke's 2004 piece on creating <a href="http://www.stuffandnonsense.co.uk/archives/creating_colour_palettes.html">colour palettes</a>. At the bottom of that page (when I found it some years later) was a link to a <a href="http://slayeroffice.com/tools/color_palette/">web app</a> that created the relevant CSS hex values.</p>
<h2 id="roll-on-some-years" tabindex="-1">Roll on some years</h2>
<p>So, as I'm sure you're aware, I use Sass (SCSS). Recently I saw Andy included this colour palette idea into his <a href="http://malarkey.github.io/Rock-Hammer/">Rock Hammer project library</a>. I had a quick peek <a href="https://github.com/malarkey/rock-hammer/">under the hood</a> (or in the github repo) and saw how he was creating the colour palettes. Where he uses RGBA to give a representation of the possible colours from your primary, secondary or tertiary choices.</p>
<h2 id="to-the-pen" tabindex="-1">To the Pen</h2>
<p>I then went swiftly to a fresh codepen and created a little bit of SCSS and HTML to recreate the palettes but using Sass's tint and shade colour functions. With this pen you would pass a primary($base-color), secondary($comp-color) and tertiary($tertiary-color) set of colour variables and it would then create a nice set of colour palettes.</p>
<p>This pen, found here - <a href="http://codepen.io/sturobson/pen/haiIe">http://codepen.io/sturobson/pen/haiIe</a> - can be taken an 'dropped' into a living styleguide (note: this is all a work in progress for my own Sass 'framework' and my HTML/CSS/JS starting point).</p>
<h2 id="there's-always-a-but" tabindex="-1">There's always a but</h2>
<p>That's all well and good, it looks nice. But the way I set the page up using nth:child wasn't very good for actual use in a project so I decided to make a quick mixin.</p>
<p>This mixin has two variables within it. $color can be a hex colour or on of the variables from your styleguide or similar. There's alse $change where you'd want to lighten(tint) or darken(shade) the colour or not (which why it's predefined as 'n'. -</p>
<p>@mixin bgcolor($color, $change: n) {
@if $change == n {
background-color: $color;
}
@if $change == l1 {
background-color: tint($color, 10%);
}
@if $change == l2 {
background-color: tint($color, 25%);
}
@if $change == l3 {
background-color: tint($color, 50%);
}
@if $change == l4 {
background-color: tint($color, 75%);
}
@if $change == d1 {
background-color: shade($color, 10%);
}
@if $change == d2 {
background-color: shade($color, 25%);
}
@if $change == d3 {
background-color: shade($color, 50%);
}
@if $change == d4 {
background-color: shade($color, 75%);
}</p>
<p>}</p>
<p>So by having our chosen colours for the design set up as variables from your styleguide, for example -</p>
<p>$base-color: #D13500;
$comp-color: #398CC2;
$tertiary-color: #dd4400;
$black: #000;
$white: #FFF;</p>
<p>We can now add a background colour to an element in our CSS that's from the colour palette we've got in our styleguide and $change is how you'd want to change the $color lightening (l) or darkening (d) it in 1 of 4 possible steps.</p>
<p>To do this you'd just @include the mixin into your CSS, for example</p>
<p>.an-example {
@include bgcolor($comp-color, d3);
}</p>
<p>which would give you the compiled CSS as -</p>
<p>.an-example {
background-color: #1c4661;
}</p>
<h2 id="making-text-colourful" tabindex="-1">Making text colourful</h2>
<p>That's good for background-color, but there's probably opurtune times when you'd like to use the colour palette colours on the color element too. So for that we can create this mixin. This mixin again has two variables. Both the same as the background colour mixin -</p>
<p>@mixin color($color, $change: n) {</p>
<p>@if $change == n {
color: $color;
}
@if $change == l1 {
color: tint($color, 10%);
}
@if $change == l2 {
color: tint($color, 25%);
}
@if $change == l3 {
color: tint($color, 50%);
}
@if $change == l4 {
color: tint($color, 75%);
}
@if $change == d1 {
color: shade($color, 10%);
}
@if $change == d2 {
color: shade($color, 25%);
}
@if $change == d3 {
color: shade($color, 50%);
}
@if $change == d4 {
color: shade($color, 75%);
}</p>
<p>}</p>
<p>So we can use the mixin like this -</p>
<p>.an-example {
@include color($comp-color, d3);
}</p>
<p>which would give you the compiled CSS as -</p>
<p>.an-example {
color: #1c4661;
}</p>
<h2 id="box-it-with-borders" tabindex="-1">Box it with borders</h2>
<p>We're getting some nice mixins out of this colour palette idea. What about borders? We like using borders and perhaps we want to have border colours from the colour palette that we've decided upon.</p>
<p>So to create this I decided to also allow for top, bottom, left and right border THINGS. So with this mixin there are 5 variables. £color and $change are the same except I've given them defaults of a black colour #000 and n for $change which I've used to express no change in colour. $border-size for the border thickness, $border-style for the style and $border-position for top, bottom, left or right -</p>
<p>@mixin border($color: #000, $border-size: 1px, $border-style: solid, $border-position: null) {</p>
<p>@if $border-position == null {
@if $change == n {
border-#{$border-position}: $border-size $border-style $color;
}
@if $change == l1 {
border: $border-size $border-style #{tint($color, 10%)};
}
@if $change == l2 {
border: $border-size $border-style #{tint($color, 25%)};
}
@if $change == l3 {
border: $border-size $border-style #{tint($color, 50%)};
}
@if $change == l4 {
border: $border-size $border-style #{tint($color, 75%)};
}
@if $change == d1 {
border: $border-size $border-style #{shade($color, 10%)};
}
@if $change == d2 {
border: $border-size $border-style #{shade($color, 25%)};
}
@if $change == d3 {
border: $border-size $border-style #{shade($color, 50%)};
}
@if $change == d4 {
border: $border-size $border-style #{shade($color, 75%)};
}
}</p>
<p>@elseif $border-position != null {
@if $change == n {
border-#{$border-position}: $border-size $border-style $color;
}
@if $change == l1 {
border-#{$border-position}: $border-size $border-style #{tint($color, 10%)};
}
@if $change == l2 {
border-#{$border-position}: $border-size $border-style #{tint($color, 25%)};
}
@if $change == l3 {
border-#{$border-position}: $border-size $border-style #{tint($color, 50%)};
}
@if $change == l4 {
border-#{$border-position}: $border-size $border-style #{tint($color, 75%)};
}
@if $change == d1 {
border-#{$border-position}: $border-size $border-style #{shade($color, 10%)};
}
@if $change == d2 {
border-#{$border-position}: $border-size $border-style #{shade($color, 25%)};
}
@if $change == d3 {
border-#{$border-position}: $border-size $border-style #{shade($color, 50%)};
}
@if $change == d4 {
border-#{border-position}: $border-size $border-style #{shade($color, 75%)};
}
}</p>
<p>}</p>
<p>So for a simple border with colour you can write -</p>
<p>.an-example {
@include border($base-color, l2);
}</p>
<p>Which would give you -</p>
<p>.an-example {
border: 1px solid #dc673f;
}</p>
<p>If you wanted to create a border-top you could write -</p>
<p>.an-example {
@include border($base-color, l2, 1px, solid, top);
}</p>
<p>Would give you this resulting CSS -</p>
<p>.an-example {
border-top: 1px solid #dc673f;
}</p>
<h2 id="to-the-end" tabindex="-1">To the end</h2>
<p>So we've now got three ways of bringing our styleguides colour palette into our stylesheets. I've uploaded this to my <a href="https://github.com/sturobson/sassifaction">Sassifaction</a> Sass(SCSS) mixin library and also as a <a href="http://codepen.io/sturobson/pen/cfaFv">pen on Codepen</a>.</p>
<h2 id="update-(07%2F04%2F13)" tabindex="-1">Update (07/04/13)</h2>
<p>Almost as soon as I posted this <a href="http://twitter.com/notrenton">Ryan</a> suggested I could do this with a function instead. He went off and some minutes later came back with this -</p>
<p>@function colorize($color, $change: n) {
@if $change == n {
@return $color;
}
@if $change == l1 {
@return tint($color, 10%);
}
@if $change == l2 {
@return tint($color, 25%);
}
@if $change == l3 {
@return tint($color, 50%);
}
@if $change == l4 {
@return tint($color, 75%);
}
@if $change == d1 {
@return shade($color, 10%);
}
@if $change == d2 {
@return shade($color, 25%);
}
@if $change == d3 {
@return shade($color, 50%);
}
@if $change == d4 {
@return shade($color, 75%);
}
}</p>
<p>This lets you put the colorise function where you'd want to put color in the (S)CSS. So for example (still using our colour variables) -</p>
<p>body {
color: colorize($base-color,l4);
background: colorize(#fff,d2);
border: 1px solid colorize($comp-color,d3);
}</p>
<p>Would give you this outputted css -</p>
<p>body {
color: #f3ccbf;
background: #bfbfbf;
border: 1px solid #1c4661;
}</p>
<p>Pretty neat. I'll be updating my Sassifaction code with this great titbit of code</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>My Media Query Mixin</title>
      <link href="https://www.alwaystwisted.com/articles/my-media-query-mixin.html"/>
      <updated>2013-04-01T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/my-media-query-mixin.html</id>
      <content type="html">
        <![CDATA[
        <p>I've written <a href="../post.php%EF%B9%96s=2013-01-12-the-lack-of-media-queries.html">quite</a> <a href="../post.php%EF%B9%96s=2012-05-28-how-im-rolling-my-media-queries.html">a</a> <a href="../post.php%EF%B9%96s=2012-04-28-a-common-set-of-breakpoints-to-start.html">lot</a> <a href="../post.php%EF%B9%96s=2012-08-06-a-sass-mixin-for-media-queries-and-ie.html">about</a> media queries; Playing with LESS then Sass(SCSS) has made me create mixin upon mixin to help my front-end development workflow. I think I've finally settled on something (famous last words!) that works for me and want to share it. Because sharing is good, right?</p>
<h2 id="and-the-winner-is%E2%80%A6" tabindex="-1">and the winner is…</h2>
<p>@mixin mq($point, $IE9: false, $query1: min, $query2: width) {
@if $IE9 == true{
.lt-ie9 &amp; {
@content;
}
}</p>
<p>@media (#{$query1}-#{$query2}: $point / $doc-font-size +em) {
@content;
}
}</p>
<h2 id="you-say-what%3F" tabindex="-1">You say what?</h2>
<p>This mixin allows you to define your major or minor breakpoint in pixels (it automatically converts to EMs), define the media query whether it be min or max, width or height, device height or device width. The mixin has 4 variables in it, most of which are predefined.</p>
<ul>
<li>$point : is the pixel value for your major or minor breakpoint</li>
<li>$IE9 : is predefined as false, changing this to true would include the IE9 conditional class of CSS</li>
<li>$query1 : this is for either min,max, min-device, or max-device defining the first part of the media query. Predefined as min</li>
<li>$query2 : this if for either width or height defining the second part of the media query. Predefined as max.</li>
</ul>
<p>It also fantastically has the option to copy the media query content and create a snippet prefixed with an class that'd be picked up by IE8 or less as specified in your HTML with this code -</p>
<p><!--[if IE 8]> <html class='no-js lt-ie9'> <![endif]--></p>
<p>So because it can give min,max,width,height options let's go through the examples.</p>
<h2 id="what's-up-%24doc-font-size" tabindex="-1">What's up $doc-font-size</h2>
<p>In my _variables.scss I have two variables that are related to the document font-size. One for line-height and one for font-size. The $doc-font-size variable in the mixin above needs to be defined in your Sass for this to work. Mine is generally set to 16 and my variables would read</p>
<p>$doc-font-size: 16;
$doc-line-height: 24;</p>
<p>Although, we won't be using the line-height in this mixin or any examples</p>
<h2 id="examples..." tabindex="-1">Examples...</h2>
<h3 id="1)-a-simple-min-width-media-query" tabindex="-1">1) A simple min-width media query</h3>
<p>So your media query you'd write in SCSS would be -</p>
<p>.example {
@include mq(320) {
width: 100%;
}
}</p>
<p>Which would result in -</p>
<p>@media screen and (min-width: 20em) {
.example {
width: 100%;
}
}</p>
<p>So giving the mixin no other arguements than a numeric value (a pixel value) would give you the staple media query of min-width.</p>
<h3 id="2)-a-simple-min-width-media-query-with-ie-fallback" tabindex="-1">2) A simple min-width media query with IE fallback</h3>
<p>So your media query you'd write in SCSS would be -</p>
<p>.example {
@include mq(320, true) {
width: 100%;
}
}</p>
<p>Which would result in -</p>
<p>.lt-ie9 {
.example {
width: 100%;
}
}
@media screen and (min-width: 20em) {
.example {
width: 100%;
}
}</p>
<p>So giving the pixel value and the second argument as true would mean the mixin would give the CSS for your conditional IE8 class.</p>
<h3 id="3)-a-simple-max-width-media-query" tabindex="-1">3) A simple max-width media query</h3>
<p>So your media query you'd write in SCSS would be -</p>
<p>.example {
@include mq(320, false, max) {
width: 100%;
}
}</p>
<p>Which would result in -</p>
<p>@media screen and (max-width: 20em) {
.example {
width: 100%;
}
}</p>
<p>Now adding the third argument of max, keeping the $IE9 variable is false creating a simple max-width media query.</p>
<h3 id="4)-a-simple-max-width-media-query-with-ie-fallback" tabindex="-1">4) A simple max-width media query with IE fallback</h3>
<p>So your media query you'd write in SCSS would be -</p>
<p>.example {
@include mq(320, true, max) {
width: 100%;
}
}</p>
<p>Which would result in -</p>
<p>.lt-ie9 {
.example {
width: 100%;
}
}
@media screen and (max-width: 20em) {
.example {
width: 100%;
}
}</p>
<p>Changing the $IE9 argument to true creates a simple max-width media query plus the IE8 conditional class.</p>
<h3 id="5)-a-simple-min-height-media-query" tabindex="-1">5) A simple min-height media query</h3>
<p>So your media query you'd write in SCSS would be -</p>
<p>.example {
@include mq(320, false, min, height) {
width: 100%;
}
}</p>
<p>Which would result in -</p>
<p>@media screen and (min-height: 20em) {
.example {
width: 100%;
}
}</p>
<p>By changing the forth variable to height, and stating the middle two ($IE9 and $query1) as they're defaulted in the mixin creates a simple min-height media query.</p>
<h3 id="6)-a-simple-min-height-media-query-with-ie-fallback" tabindex="-1">6) A simple min-height media query with IE fallback</h3>
<p>So your media query you'd write in SCSS would be -</p>
<p>.example {
@include mq(320, true, min, height) {
width: 100%;
}
}</p>
<p>Which would result in -</p>
<p>.lt-ie9 {
.example {
width: 100%;
}
}
@media screen and (min-height: 20em) {
.example {
width: 100%;
}
}</p>
<p>Changing the second variable of the mixin ($IE9) to true would give you the simple min-height mixin with the conditional class too.</p>
<h3 id="7)-a-simple-max-height-media-query" tabindex="-1">7) A simple max-height media query</h3>
<p>So your media query you'd write in SCSS would be -</p>
<p>.example {
@include mq(320, false, max, height) {
width: 100%;
}
}</p>
<p>Which would result in -</p>
<p>@media screen and (max-height: 20em) {
.example {
width: 100%;
}
}</p>
<p>Here we're keeping the IE9 variable as false, making the min/max/min-device/max-device as max and width/height as height to create a simple max-height media query.</p>
<h3 id="8)-a-simple-max-height-media-query-with-ie-fallback" tabindex="-1">8) A simple max-height media query with IE fallback</h3>
<p>So your media query you'd write in SCSS would be -</p>
<p>.example {
@include mq(320, true, max, height) {
width: 100%;
}
}</p>
<p>Which would result in -</p>
<p>.lt-ie9 {
.example {
width: 100%;
}
}</p>
<p>@media screen and (max-width: 20em) {
.example {
width: 100%;
}
}</p>
<p>Here we've just given the $IE9 variable a value of true giving a simple max-width media query and a conditional class for IE8.</p>
<p>From these examples I hope you can see that instead of min or max you can also use min-device and max-device so that you can target 'devices' if you wish to.</p>
<h2 id="major-breakpoints" tabindex="-1">Major Breakpoints</h2>
<p>I work with two kinds of CSS3 media queries in mind when developing responsive websites. Major and minor breakpoints. As mentioned in a <a href="http://www.slideshare.net/yiibu/pragmatic-responsive-design/24">slidedeck</a> from <a href="https://twitter.com/stephanierieger">Stephanie</a> and <a href="https://twitter.com/bryanrieger">Bryan</a> of <a href="http://yiibu.com/">Yiibu</a>.</p>
<p>With Sass you can create some variables for what you like to determine as 'major' breakpoints and include them as necessary in the media query mixin.</p>
<p>For example you could have predefined major breakpoints like this -</p>
<p>$mobile: 320;
$tablet: 760;
$desktop: 1200;</p>
<p>You can then include it in the mixin like this -</p>
<p>@include mq($mobile, false, max) {
.example {
width: 100%;
}
}</p>
<p>Which would give you this result -</p>
<p>@media screen and (max-width: 20em) {
.example {
width: 100%;
}
}</p>
<h2 id="nesting-that-media-query" tabindex="-1">Nesting that media query</h2>
<p>One of the great things about Sass is the ability to nest your CSS. But you can also nest mixins. This means you can nest this mixin. That's pretty cool. So as an example you can do something like this -</p>
<p>.example {
@include mq(320) {
width: 300px;
@include mq(480, false, max) {
background: red;
}
}
}</p>
<p>Would give you this result -</p>
<p>@media (min-width: 20em) {
.example {
width: 300px;
}
}</p>
<p>@media (min-width: 20em) and (max-width: 30em) {
.example {
background: red;
}
}</p>
<h2 id=".class-%3E-mixin-or-mixin-%3E-.class" tabindex="-1">.class &gt; mixin or mixin &gt; .class</h2>
<p>From all the examples I've given above I've been putting the media query mixin within the .class but you can do this the other way around and with Sass it outputs the same code. As shown in this example -</p>
<p>@include mq(320) {
.example {
width: 300px;
@include mq(480, false, max) {
background: red;
}
}
}</p>
<p>This gives the same results -</p>
<p>@media (min-width: 20em) {
.example {
width: 300px;
}
}</p>
<p>@media (min-width: 20em) and (max-width: 30em) {
.example {
background: red;
}
}</p>
<h2 id="media-query-bubbling-or-nesting" tabindex="-1">Media Query Bubbling or Nesting</h2>
<p>As I've written previously I write <a href="../post.php%EF%B9%96s=2012-05-05-everyday-im-bubbling-with-media-queries-and-less.html">my media queries 'inline'</a> with the element I'm editing rather than tagging it on to the bottom of my stylesheet. This, I feel, allows for better code organisation and a more OO 'modular' approach. This makes it easy to find the code you may need to edit and allows for a better 'mobile first' approach.</p>
<h2 id="support-for-ie6-and-7" tabindex="-1">Support for IE6 and 7</h2>
<p>There are two ways you could do this using the mixin. Forget about it like i do and plumb something like my set of <a href="https://github.com/sturobson/Universal-IE7">Universal IE7 Sass files</a> which is an updated 'Sass-ified' version of <a href="http://stuffandnonsense.co.uk/blog/about/universal_internet_explorer_6_css">Andy Clarkes Universal IE6</a> codebase. Or if you need to support IE6 and 7 a little better than that you could use <a href="../post.php%EF%B9%96s=2013-01-13-ie-fix-yoself.html">something like this</a> code snippet -</p>
<p>.lt-ie9 &amp; {</p>
<p>// put the IE8 and below CSS declarations here
/* IE8 and below */</p>
<p>// if you need IE7 as well then prefix the CSS with a *
/* IE7 and below */</p>
<p>// if you need IE6 as well then prefix the CSS with a _
/* IE6 */
}</p>
<p>Where you would be using CSS hacks to will Internet Explorer 6 and 7 into submission.</p>
<h2 id="portrait-%2F-landscape-mixin" tabindex="-1">Portrait / Landscape mixin</h2>
<p>Because you can nest media queries within each other. I've also created a little mixin for defining the portrait or landscape media query.</p>
<p>@mixin orient($orientation: landscape) {
@media (orientation : $orientation) {
@content;
}
}</p>
<p>So if you write a media query like this</p>
<p>@include mq(768) {
@include orient {
.example {
width: 100%;
}
}
}</p>
<p>It would give this result -</p>
<p>@media (min-width: 48em) and (orientation: landscape) {
.example {
width: 100%;
}
}</p>
<p>As you can see this mixin also has a variable for the landscape/portrait predefined as landscape. If you want a portrait media query you can write something like this -</p>
<p>@include mq(768) {
@include orient(portrait) {
.example {
width: 100%;
}
}
}</p>
<p>It would give this result -</p>
<p>@media (min-width: 48em) and (orientation: portrait) {
.example {
width: 100%;
}
}</p>
<p>Of course you can just include the media query by itself if you need to.</p>
<h2 id="100%25-pure-adrenaline!" tabindex="-1">100% pure adrenaline!</h2>
<p>After all this, what I've effectively done is recreate a Compass plugin by <a href="https://twitter.com/snugug">Sam</a> and <a href="https://twitter.com/codingdesigner">Mason</a> - <a href="http://breakpoint-sass.com/">Breakpoint</a>. You could say I've reinvented the wheel a little. But I like my mixin, it works for me and how I want to code. Also I don't use Compass because I like 'my own' code and to know what each mixin I use is doing. But that's just me. If you're already a Compass user your mindset might be in favour of using this plugin. As with all things, it depends.</p>
<h2 id="copy-and-paste" tabindex="-1">Copy and Paste</h2>
<p>As well as copying and pasting the code above, I've also added it on <a href="http://codepen.io/sturobson/pen/keuyp">codepen</a> and to my (work in progress (just started)) Sass mixin library - <a href="https://github.com/sturobson/sassifaction">Sassifaction</a>.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Toggling Bad Design</title>
      <link href="https://www.alwaystwisted.com/articles/toggling-bad-design.html"/>
      <updated>2013-03-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/toggling-bad-design.html</id>
      <content type="html">
        <![CDATA[
        <p>This week has seen a flurry of posts about the possibility of adding a 'toggle' to our websites so that if a user wants to see the 'full' site they can flip a switch and the responsive design will just go away.</p>
<h2 id="we-got-ourselves-a-reader" tabindex="-1">We got ourselves a reader</h2>
<p>I remember reading Bruce Lawsons <a href="http://www.brucelawson.co.uk/2013/turning-off-responsive-web-design/">post</a> about this and stating in the comments that responsive design is <a href="http://www.brucelawson.co.uk/2013/turning-off-responsive-web-design/#comment-1275428">'more than just a technical happenstance'</a>. Later on reading Alex's post <a href="http://mistermorris.tumblr.com/post/44777883384/the-accessibility-of-media-queries-and-user-choice">about this</a> at the start of March. I thought it was a nice idea, having tweeted with Alex about it t] we both agree it should be at a 'browser' level and not something we (as designers and developers) should be worrying about.</p>
<p>This week Roger Johansson wrote <a href="http://www.456bereastreet.com/archive/201303/letting_users_disable_responsive_layout/">a post of similar ilk</a>, showing us that it's not really 'a lot of work' to implement it. Jordan Moore took this post and added <a href="http://www.jordanm.co.uk/post/46286897572/thoughts-on-toggling-a-responsive-design-on-and-off">some notes</a> to it telling us that he wished 'I had a toggle for the bad responsive designs, the ones that “don’t get it'.” and came up with an idea for icons for the user to easily choose from.</p>
<p>That Andy Clarke took Jordan's icon idea and made some more <a href="http://www.stuffandnonsense.co.uk/blog/about/a-suggestion-for-responsive-design-toggle-icons">simpler icons</a> that site visitors would moreover understand.</p>
<h2 id="unsurprisingly-me" tabindex="-1">Unsurprisingly me</h2>
<p>I (unsurprisingly) think this is a cop-out. If you think that we should be giving the site visitor the option to turn off your device agnostic design so they get a desktop view. You've not done your job correctly in the first plate.</p>
<p>As Jordan says he wants to turn off RWD on bad sites. Understandable as this is it should be something mitigated at the browser level.</p>
<p>The problem herein lies, I feel, with bad design, bad decisions and bad implementation. If you're 'doing your job' properly your responsive design should be perfect for the visitors needs so that they don't have to 'turn it off'.</p>
<p>You should be testing your designs with actual users, solving problems as best is possible. Which, may mean not even going down a responsive route. It is not a panacea.</p>
<p>We shouldn't as web designers/developers thinking of including such a toggle as it undermines the work we've created for our clients and their users. It's like asking MacDonald's to make you a double egg mcmuffin after 10.30am.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Search, it&#39;s gonna be big</title>
      <link href="https://www.alwaystwisted.com/articles/search-its-gonna-be-big.html"/>
      <updated>2013-03-01T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/search-its-gonna-be-big.html</id>
      <content type="html">
        <![CDATA[
        <p>The mobile device you have in your pocket or in your hand whilst reading this has, effectively, been around for a long time. I'd suggest for brevity that around 1983 when the <a href="http://en.wikipedia.org/wiki/Motorola_DynaTAC">Motorola DynaTAC</a> was launched is a good date to pick.</p>
<p>With this, I'd surmise, came a new and/or increasingly used interaction. Pushing buttons with a finger or thumb from one hand whilst holding the device in the other. So for 30 years our muscle memory has been learning and adapting to this interaction so it's essentially become a second nature.</p>
<p>Today there's more mobile phones out there that could possibly be connected to the internet than you can <a href="http://gadgets.ndtv.com/mobiles/news/samsung-apple-dominate-smartphone-sales-in-q4-2012-nokia-and-rim-aim-to-catch-up-analysts-320371">shake a stick at</a>. So the interaction between device, eyes, hands and fingers is used for swiping, tapping screens and the such.</p>
<h2 id="the-decrepit-navigation-bar" tabindex="-1">The decrepit navigation bar</h2>
<p>Since we started designing sites we included links to pages and other sites. When time moved forward and gave us opportunities to stylise these links we created horizontal and vertical 'nav bars'.</p>
<p>When the mobile device came out and we started going mobile we tailored the navigation for it. We started off making the navigation a long list realising that content was more important to a site visitor we started hiding it or moving it so that the visitor would see the content first with navigation one click/tap/pull/push/interaction away.</p>
<p>Navigation could still possibly be complex. Drop-downs turned into show and hide navigation within show and hide navigation. It seems logical, hiding it away for the visitor to find by drilling down to the link that they need.</p>
<h2 id="but-what-if-we-don't-need-the-navigation" tabindex="-1">But what if we don't need the navigation</h2>
<p>Our hands, fingers and thumbs are so used to the tactile interaction of the with a device now that I keep thinking –</p>
<blockquote>
<p>'Would asking the user to use a search form element be a better experience for them when visiting our sites?'</p>
</blockquote>
<p>A search box which we could coax into auto-suggestting the main navigation when the visitor starts typing 'about' or 'news' for example but allowing them to drill down to the content they need if the wish to.</p>
<p>This way you're not deciding what you think your user needs from your site. You're allowing them to find it and possibly find stuff they weren't aware of.</p>
<h2 id="possibly-possible%2C-it-depends" tabindex="-1">Possibly possible, it depends</h2>
<p>Of course, it depends, but who decided to have a 'main navigation bar' for sections (see chapters) of a website. A methodical way of making groups of 'pages' into something coherent on a fluid web where a visitor would (now) more often than not (I suggest) coming from a search engine.</p>
<p>Perhaps we don't need those 'main' links on some sites. Perhaps we could use 'search' as a better facilitator for narrow viewports (specifically mobile devices) where the interaction (more often than not) would be touching and tapping the glass that's displaying the website.</p>
<p>A possibility dependant.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>max-width your face off</title>
      <link href="https://www.alwaystwisted.com/articles/max-width-your-face-off.html"/>
      <updated>2013-02-22T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/max-width-your-face-off.html</id>
      <content type="html">
        <![CDATA[
        <p>Something I am coming across once in a while is a site that's effectively a single column up to 767 or so pixels. Personally, I find this a little lazy and would suggest time and inclination are the underlying reasons.</p>
<blockquote>
<p>'Let's just stack the content until we reach 'the iPad' at portrait'<br>
- a. developer / a. designer / a. cheque writer</p>
</blockquote>
<p>Unfortunately it's also easy to create this type of 'design' for a narrow view. A quick fix that would make your site look (possibly) lovely on a handheld device.</p>
<p>You could write something as simple as this -</p>
<p>@media (max-width: 767px) {
* {
float: none;
margin: 0;
padding: 0 10px;
width: 100%;
}
}</p>
<p>and the job would be done. Your site would now be, more or less, responsive. It could nicely stack your content in source order of your HTML.</p>
<h2 id="but-that's-crap" tabindex="-1">But that's crap</h2>
<p>In doing this what you're essentially doing is letting the browser compute all of the CSS it's downloaded then override most of it with the max-width rule. A quick (and lazy) fix with a slight performance performance issue.</p>
<p>This would (I'd surmise) be happening when you've developed from the top down. Where you'd get a .psd of the 'desktop view' and you'd have to make it responsive.</p>
<p>You can still make it responsive but you don't need to overwrite all those rules, you can still start from the ground up. It'd be a cleaner way. You'd be <a href="http://alwaystwisted.com/post.php?s=2013-01-12-the-lack-of-media-queries">using the cascade</a> for what it is rather than hacking it as an afterthought.</p>
<p>Next time, try it. It might take a little longer (budget for it) but the next time and the time after that you'd get quicker and quicker at it, if it's needed.</p>
<h2 id="more-than-your-problem" tabindex="-1">More than your problem</h2>
<p>I would argue that as a developer who only gets a 'desktop view' of the design you're only doing the best you can. We need to start educating clients that if they need a responsive site they need to be part of a reiterative process through constant communication and decision making.</p>
<p>Making second guesses as to what's needed from a site that's only got a 'desktop view' is (possibly) not going to make for a great responsive user experience.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Tools of my trade, part 1</title>
      <link href="https://www.alwaystwisted.com/articles/tools-of-my-trade-part-1.html"/>
      <updated>2013-02-11T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/tools-of-my-trade-part-1.html</id>
      <content type="html">
        <![CDATA[
        <p>So I've been (properly) freelancing for just over a month and thought it'd be nice to write a post on the hardware and software I'm using currently to make things happen.</p>
<p>This might be quite an exhaustive list of 'bits and bobs' but they're not all from within the last 30 days or so. My 'tools' have been gather over the last 3 years of 'doing web properly'. This would explain why there's so many testing devices. This is the first post, just quickly discussing the hardware I use daily.</p>
<h2 id="the-hardware" tabindex="-1">the hardware</h2>
<p><img src="/images/articles/fdde2ff060d211e2904b22000a1f8c1d7-ck.jpg" alt="my office space" loading="lazy" decoding="async"></p>
<p>I've got quite a bit of hardware which I've collected and/or purchased over the last 12 months or so. Here's a full and (slightly) detailed list.</p>
<h3 id="macbook-air" tabindex="-1">MacBook Air</h3>
<p>So my main machine is a late 2011 13' Macbook Air. It's the stock model so there's only 4GB of RAM and a 128GB hard disk. I did have a Macbook Pro but that (really) hurt my back if I ever took it with me in my bag. The Air is so light I have to check sometimes to see if I've got it.</p>
<h3 id="griffin-laptop-stand" tabindex="-1">Griffin Laptop Stand</h3>
<p>Bringing the air up around 5 inches making it that little closer to eye level for the casual glance.</p>
<h3 id="time-capsule" tabindex="-1">Time Capsule</h3>
<p>I've got a 2TB Apple Time Capsule for backing up my Air, set once and forgotten. So far, touch wood, I've not had to use it. But I'm sure there'll be a day.</p>
<h3 id="23'-monitor" tabindex="-1">23' Monitor</h3>
<p>I'm generally at my desk when I'm working so my laptop is connected to a 23' Dell Ultrasharp monitor. It's pretty good and all those extra pixels really help day in, day out. I've also got the 'sound bar' speaker system that screws onto the monitor too. Not the greatest sound in the world but after a few tweaks of the EQ in iTunes it's pretty good.</p>
<h3 id="apple-wired-keyboard%2C-magic-mouse-%26-mobee-magic-mouse-charger" tabindex="-1">Apple Wired Keyboard, Magic Mouse &amp; Mobee Magic Mouse Charger</h3>
<p>I really miss a numpad, I've used the wireless keyboard before and of course the Air doesn't have a numpad but I'm finding it really useful for doing 'all that maths' with responsive web design.<br>
Although I've got a trackpad on my Air I find that I still need to have 'a mouse' when I'm working in a 'desktop' scenario. The Magic Mouse is perfect for me for this. It's a bit weighty with two batteries installed and batteries cost a lot.<br>
I've installed the Mobee rechargeable battery to it. Makes the mouse that little bit lighter too as it only feels like there's one AA (LR6) battery inside.</p>
<h3 id="blue-snowball-usb-mic" tabindex="-1">Blue Snowball USB Mic</h3>
<p>I don't really like talking to people. Needs must when the devil drives and I've found that using this mic for Skype is perfect. It's so close to the speakers in my setup just proving that the cardioid pattern is so tight there's no feedback at all.</p>
<h3 id="usb-charger-%2F-display" tabindex="-1">USB Charger / Display</h3>
<p>I've got several devices that I test with (I'll blog about those too, soon) that need charging. I've found this little Belkin Valet USB charging 'table'. It allows you to charger 4 phones (not iPads unfortunately) and has space for 3 phones on it's surface. This works great as I've got a dock for my iPhone that connects to it. So that's a 'droid 2.2, 2.3 a WP7 phon and a iPhone all in front of me 'at the ready'.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>The perils of freelancing, month one.</title>
      <link href="https://www.alwaystwisted.com/articles/the-perils-of-freelancing-month-one.html"/>
      <updated>2013-02-07T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/the-perils-of-freelancing-month-one.html</id>
      <content type="html">
        <![CDATA[
        <p>So, one month to this day I ventured out into the 'real world' and started freelancing fulltime. Leaving my old 9 to 5 job and working evenings on the side making the side job the full time gig.</p>
<p>But, what have I been up to? I'll just quickly sumarise my first month in the hope that a) I feel i've achieved something in the last 30(odd) days and b) well, take from that it what you will.</p>
<p>So,  allons-y.</p>
<h2 id="the-work" tabindex="-1">the work</h2>
<p>The jobs I've been lucky enough to be offered and take on this month have been varied. A good thing. Keeps your chops down. So what were they? In relative order of play they were...</p>
<p>I started my first month by finishing off a client project from before Christmas when I was 'just a part-timer'. The project was to create the flat HTML, CSS and JS for a site that was responsive that then would be plumbed into the back-end. This project was a great one to work on, it allowed me to really get to grips with Mixture and helped speed up my development process.</p>
<p>Whilst finishing this job off I started my first new contract for a client who specialises in emails design and strategy. Taken the designs turning them into code and making them responsive. A great continuation of a client relationship started pre-fulltime this project is still on going but hopefully it'll be signed off and live soon.</p>
<p>I also started with a short contract of retro-fitting an HTML5 audio player so that it fits viewport widths from 280px and up. The client wanted to be able to offer their clients a 'plugin-able' audio player that takes them to the host site to buy audio tracks. This was great. I learnt alot about iframes, what you can and can't do with them and managed to create a solution true to the players original design and I only touched the CSS.</p>
<p>Next up, was a learning lesson. An 'out of the blue' email, a flurry of skype conversations and a small gig to create a responsive pagination pattern. All went well. Day three on the project I got 'an inkling'. The client went hot and cold and thus far I've had not further conversation with them. You could mark this down as part of the learning curve. Getting things in stone etc. I know. This was a moment of madness where I forgot 'contracts' and the such. I did learn lots though, every cloud.</p>
<h2 id="the-outgoings" tabindex="-1">the outgoings</h2>
<p>As well as my nominal monthly out goings for the business. I've also spent some money on 'things'. I've purchased an old Nokia S60 device for the test suite and I also nabbed a ticket to the ampersand conference down in Brighton.</p>
<h2 id="closing-notes" tabindex="-1">closing notes</h2>
<p>So that's pretty much my first month. Down on paper it seems like I've hardly 'done' anything. I'm sure I've missed stuff and I've no doubt been as verbose as I could have been, but this was an attempt to summarise after all.</p>
<p>And, how have you been?</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>More Podcasts than you can shake a stick at</title>
      <link href="https://www.alwaystwisted.com/articles/more-podcasts-than-you-can-shake-a-stick-at.html"/>
      <updated>2013-01-21T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/more-podcasts-than-you-can-shake-a-stick-at.html</id>
      <content type="html">
        <![CDATA[
        <p>Back in April last year I wrote a short post <a href="http://alwaystwisted.com/post.php?s=2012-04-07-listen-everyday">gathering together some podcasts</a> I listen to. It seems thus far that 2013 is turning out to be a year for podcasts. <a href="https://twitter.com/StuRobson/status/291107846676967424">That's amazing!</a>. Here's a list of podcasts that you should now give your grubby ears the joy of listening to.</p>
<h2 id="besquare" tabindex="-1"><a href="http://www.besquare.me/podcasts/">BeSquare</a></h2>
<p>As well as <a href="http://twitter.com/craiginwales">@craiginwales</a> fantastic resource of collection conference videos you couldn't get to go to. He's also been creating some video and audio podcast interviews with some stalwarts of the industry</p>
<h2 id="happy-monday-podcast" tabindex="-1"><a href="http://happymondaypodcast.com/">Happy Monday Podcast</a></h2>
<p>A new, short-burst, industry podcast available every Monday from 7am GMT from <a href="http://twitter.com/sazzy">@sazzy</a> and <a href="http://twitter.com/joshlong">@joshlong</a></p>
<h2 id="the-back-to-front-show" tabindex="-1"><a href="http://backtofrontshow.com/">The Back to Front Show</a></h2>
<p>Weekly 'web focused' musings from <a href="https://twitter.com/keirwhitaker">@keirwhitaker</a> and <a href="http://twitter.com/kieranmasterton">@kieranmasterton</a></p>
<h2 id="less-than-bang" tabindex="-1"><a href="http://lessthanbang.com/">Less Than Bang</a></h2>
<p>A show by and for young &amp; attractive web people from <a href="http://twitter.com/pauladamdavis">@pauladamdavis</a> and <a href="http://twitter.com/phuunet">@phuunet</a></p>
<h2 id="unfinished-business" tabindex="-1"><a href="http://unfinished.bz/">Unfinished Business</a></h2>
<p>From <a href="http://twitter.com/malarkey">@malarkey</a> and <a href="http://twitter.com/annadebenham">@annadebenham</a> discussing the business side of web things</p>
<h2 id="quit!" tabindex="-1"><a href="http://5by5.tv/quit">Quit!</a></h2>
<p>From podcast mogul <a href="http://twitter.com/danbenjamin">@danbenjamin</a>, a live call-in show helping people sort their lives out.</p>
<h2 id="the-web-ahead" tabindex="-1"><a href="http://5by5.tv/webahead">The Web Ahead</a></h2>
<p>Another <a href="http://5by5.tv">5by5.tv</a> show hosted by <a href="http://twitter.com/jensimmons">@jensimmons</a> talking all things relevant and topical in the web. Bonus: includes 'The Web Behind' with co-host <a href="http://twitter.com/meyerweb">@meyerweb</a> talking about the history of the web</p>
<h2 id="bizcraft" tabindex="-1"><a href="http://unmatchedstyle.com/bizcraft">BizCraft</a></h2>
<p>Another business-side podcast that's worthy of a listen.</p>
<h2 id="upfront-podcast" tabindex="-1"><a href="http://upfrontpodcast.com/">Upfront Podcast</a></h2>
<p>A weekly web development podcast by <a href="http://twitter.com/Jack_Franklin">@Jack_Franklin</a> and <a href="http://twitter.com/benhowdle">@benhowdle</a>.</p>
<h2 id="the-port80-podcast" tabindex="-1"><a href="http://port80events.co.uk/podcasts/">The Port80 Podcast</a></h2>
<p>Where <a href="http://twitter.com/joel_hughes">@joel_hughes</a> talks to 'various web folk about the stuff they do and why they do it.'</p>
<p>These are 'out' but there's a couple to keep an eye out for too...</p>
<h2 id="beyond-ink" tabindex="-1"><a href="http://beyondink.co.uk/">Beyond Ink</a></h2>
<p>From <a href="http://twitter.com/missrachilli">@missrachilli</a> and coming soon a new web-design podcast that aims to help us understand our craft more than ever before</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>IE Fix Yo&#39;self!</title>
      <link href="https://www.alwaystwisted.com/articles/ie-fix-yoself.html"/>
      <updated>2013-01-13T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/ie-fix-yoself.html</id>
      <content type="html">
        <![CDATA[
        <p>A while back I was developing a site and got to thinking about the conditional classes I was using in my HTML to allow me to specific 'fixes' for IE6,7 &amp; 8.</p>
<p>It seemed a little verbose to have 3 lines at the top of my HTML document 'just in case' a visitor was using an older browser.</p>
<h2 id="to-the-internet!" tabindex="-1">To the internet!</h2>
<p>I went a googling and came across this post from <a href="http://twitter.com/mathias">@mathias</a> - <a href="http://mathiasbynens.be/notes/safe-css-hacks">In defense of CSS hacks</a> and was convinced that applying hacks to the CSS as and when needed would be much nicer for my development process (and sanity).</p>
<h2 id="pen-it." tabindex="-1">Pen it.</h2>
<p>So I threw open a new <a href="http://twitter.com/codepen">@codepen</a> and created - <a href="http://codepen.io/sturobson/pen/oJEwg">IE fix yo'self</a>. It's a snippet for my pre-processor of choice (Sass (SCSS syntax)). I've got it set up in Coda 2 now so that I can quickly get that 'template' up and running as soon as possible and allow me to 'hack' if needed IE6 &amp; 7.</p>
<p>It looks like this -</p>
<p>.an-example {</p>
<p>// put the IE9 and 'other' browser CSS declarations here</p>
<p>.lt-ie9 &amp; {</p>
<p>// put the IE8 and below CSS declarations here
/* IE8 and below */</p>
<p>// if you need IE7 as well then prefix the CSS with a *
/* IE7 and below */</p>
<p>// if you need IE6 as well then prefix the CSS with a _
/* IE6 */</p>
<p>}
}</p>
<h2 id="386'ing-(not-really)" tabindex="-1">386'ing (not really)</h2>
<p>Today I saw a tweet from the <a href="http://twitter.com/H5BP">HTML5 boilerplate</a> account <a href="https://twitter.com/h5bp/status/290530820370866177">saying</a> they've opened <a href="https://github.com/h5bp/html5-boilerplate/issues/1290">a discussion about 'dropping' conditional class support for IE</a> which reminded me of this snippet.</p>
<p>I think it's <a href="https://github.com/h5bp/html5-boilerplate/issues/1290#issuecomment-12201585">probably a good thing</a> for the boilerplate to drop support for conditional classes. But hope they point developers as to the reasons why and how to 'hack' around it. Using something like the code example above.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>The lack of media queries</title>
      <link href="https://www.alwaystwisted.com/articles/the-lack-of-media-queries.html"/>
      <updated>2013-01-12T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/the-lack-of-media-queries.html</id>
      <content type="html">
        <![CDATA[
        <p>In a <a href="http://www.slideshare.net/bryanrieger/rethinking-the-mobile-web-by-yiibu">Yiibu presentation</a> from September 2010 slide <a href="http://www.slideshare.net/bryanrieger/rethinking-the-mobile-web-by-yiibu/79">79</a>, had this sentence.</p>
<p>'the absence of support for @media queries is in fact the first @media query…'</p>
<p>So any browser on any machine that doesn't support media queries will have this one true 'media query' from the outset.</p>
<h2 id="have-i-told-you-lately%3F" tabindex="-1">Have I told you lately?</h2>
<p>What I'm seeing lately are designs created from 320 pixels and upwards (not Andy's fantastic boilerplate). Which is great if your have a browser viewport that's 320px wide. But 'the mobile web' doesn't start at 320px.</p>
<p>Recently <a href="http://twitter.com/snugug">Sam Richard</a> posted an overview of his <a href="http://snugug.com/musings/amusing-analytics-december">browser statistics for December 2012</a>. Although screen resolution doesn't necessarily equate to a devices viewport. You could easily be breaking your site if you only start optimising the design from 320px.</p>
<h2 id="baseline-first" tabindex="-1">Baseline first</h2>
<p>On January 9th <a href="http://twitter.com/adactio">Jeremy</a> wrote a <a href="http://adactio.com/journal/5964/">brief musing</a> on supporting IE in a media queried world. In it he mentions 'linearised content with baseline styles'. That is what we should be doing first.</p>
<p>In the code.</p>
<p>Before you even think about the layout on your popular device from 320 and up code as if the design is a complete 'stack and scroll' device.</p>
<h2 id="basics-first" tabindex="-1">Basics First</h2>
<p>Add your HTML, include your reset then only add font sizes, families, weights. Include colours and minimal margins and paddings to your CSS. Don't float. Don't make a horizontal navigation. No gradients, no rounded corners. Just the basics.</p>
<h2 id="doit.gif" tabindex="-1">doit.gif</h2>
<p>Doing this will give you good stead for the devices and browsers that don't support media queries and the ones that do but are smaller than 320px.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Don&#39;t do this in responsive web development</title>
      <link href="https://www.alwaystwisted.com/articles/dont-do-this-in-responsive-web-development.html"/>
      <updated>2013-01-10T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/dont-do-this-in-responsive-web-development.html</id>
      <content type="html">
        <![CDATA[
        <p>I've just read this article from <a href="http://twitter.com/netmag">@netmag</a> on how to <a href="http://www.netmagazine.com/tutorials/build-basic-responsive-site-css">'build a responsive site with CSS'</a> and wanted to quickly share something.</p>
<p>In the post (a republication of an article they printed in June/July of 2012) they quickly discuss the meta tag for <a href="https://developer.mozilla.org/en-US/docs/Mobile/Viewport_meta_tag">viewport</a>.</p>
<p>In the example code they use the maximum-scale, like this –</p>
<p><meta name='viewport' content='width=device-width, minimum-scale=1.0, maximum-scale=1.0' /></p>
<p>This stops the user from zooming into your site. Yes you've designed it and coded it for a narrow viewport from something like an iPhone. That doesn't mean the sites visitor doesn't want to zoom in, perhaps they have difficulty with their sight.</p>
<p>So please. Don't include that. Use this instead –</p>
<p><code>&lt;meta name='viewport' content='width=device-width, minimum-scale=1.0' /&gt;</code></p>
<p><meta name='viewport' content='width=device-width, initial-scale=1.0' /></p>
<p>This means the visitor can zoom into the site (perhaps to take a finer look at a photo) and is a quick accessibilty win.</p>
<h2 id="update." tabindex="-1">Update.</h2>
<p>I was asked on twitter how I handle the <a href="https://twitter.com/Sheerman/status/289339346937597952">'orientation-change zoom-screwery'</a> I mentioned that (thus far) I've not found any botheration from clients that it does this (sidenote: perhaps it's a 'developer thing').</p>
<p>But there is a fix from the guys at <a href="http://twitter.com/filamentgroup">Filament Group</a> using Javascript which is discussed in <a href="http://filamentgroup.com/lab/a_fix_for_the_ios_orientationchange_zoom_bug/">this fine blogpost</a> from <a href="http://twitter.com/scottjehl">Scott Jehl</a>.</p>
<h2 id="update-updated." tabindex="-1">Update Updated.</h2>
<p>I had a quick tweet from @snugug reminding me that the orientation bug is fixed in iOS 6+ and recommending using initial-scale rather than minimum-scale (which I agree with and have updated the post).</p>
<h2 id="update%2C-update-updated." tabindex="-1">Update, Update Updated.</h2>
<p>On the 23rd of October I looked into the code of a newly launched site to see</p>
<p><meta name='viewport' content='user-scalable=no, width=device-width, minimum-scale=1.0, maximum-scale=1.0' /></p>
<p>Needless to say, don't do that either. Adding:</p>
<p>user-scalable=no</p>
<p>Is just as bad.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Develop your styleguides with code</title>
      <link href="https://www.alwaystwisted.com/articles/develop-your-styleguides-with-code.html"/>
      <updated>2013-01-10T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/develop-your-styleguides-with-code.html</id>
      <content type="html">
        <![CDATA[
        <p>I've recently read a lovely post by <a href="http://twitter.com/markboulton">Mark Boulton</a> where he touches on our <a href="http://markboulton.co.uk/journal/abstractions">current fascination</a> with styleguides, pattern libraries and primers.</p>
<p>I'd like to give my take on it.</p>
<p>I'm just going to ratify what I often say and that is I'm not a designer. I just can't do it as good as other people so I don't.</p>
<p>I love HTML, CSS and JS (kinda) and (blowing my own trumpet) I'm pretty good at it.</p>
<h2 id="frickin'-love-styleguides" tabindex="-1">Frickin' love styleguides</h2>
<p>Or pattern libraries, or <a href="http://adactio.com/journal/5028/">pattern primers</a>. They help me code more effeciently in that object orientated kind of way. I don't mean I need a .psd file of 'all the things'.</p>
<p>How I approach creating a coded styleguide is pretty basic.</p>
<ol>
<li>print out 'pages' in grayscale</li>
<li>attach tracing paper</li>
<li>make pretty boxes</li>
<li>define naming convention</li>
<li>start coding</li>
<li>re-iterate</li>
<li>re-iterate</li>
</ol>
<p>This stops me from duplicating code and allows me to check changes 'globally'.</p>
<h2 id="be-appropriate" tabindex="-1">Be appropriate</h2>
<p>I think styleguides as I seem them in web design are for the developer more than the designer. I feel the designer should be thinking about the 'bigger picture' in fixing the problem for their client.</p>
<p>The developer should be making their best effor in coding it as leanly, cleanly as possible. To get that you should really be trying to make a pattern library or <a href="https://github.com/snugug/style-sites">styleguide</a> with your code.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Structuring my Sass 101, part 3.</title>
      <link href="https://www.alwaystwisted.com/articles/structuring-my-sass-101-part-3.html"/>
      <updated>2013-01-08T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/structuring-my-sass-101-part-3.html</id>
      <content type="html">
        <![CDATA[
        <p>note: This is not a guide. This is just how I choose to do things.</p>
<p>In the first post I discussed <a href="http://alwaystwisted.com/post.php?s=2013-01-07-structuring-my-sass-101-part-1">my file structure</a>, in the 2nd I gave a brief overview of how I <a href="http://alwaystwisted.com/post.php?s=2013-01-07-structuring-my-sass-101-part-2">import everything for compiling my CSS</a>.</p>
<p>In this post I'm going to discuss my _variables.scss file and my (personal) _mixins.scss file.</p>
<h2 id="_variables.scss" tabindex="-1">_variables.scss</h2>
<p>This is pretty self explanitory really. In this file I keep all the Sass variables that I'd be using throughout the project. So this could include colors, font-families, initial document settings (like font-size and line-height), gutters.</p>
<p>These individual variables are grouped and seperated  by a comment. So it would look something like this.</p>
<p>// initial variables set-up</p>
<p>$doc-font-size:16;
$doc-line-height:24;</p>
<p>// gutter for grids</p>
<p>$gutter: 2.1666667%;</p>
<p>// colors</p>
<p>$dark-grey: #5e5e5e;
$dark-red: #b50000;</p>
<p>// font family</p>
<p>$header-font:	'futura-pt',sans-serif;
$content-font:	'proxima-nova',sans-serif;</p>
<p>This file is opened once in a while, for adding things usually. Keeping all my variables in one place means I won't have to hunt for it later when I see it referenced but can't find it to change it.</p>
<h2 id="_mixins.scss" tabindex="-1">_mixins.scss</h2>
<p>Using a file like this you can tell that I don't use something like Compass or Bourbon (unless required by a client). This is because I like to write my own mixins so I know what the mixin does and how it'll nicely output when compiled. So this file is where I keep my font-size mixin for REMs w/ a px fallback that I can also set or auto-create the line height and bottom margin for. There's a function for just creating the font-size REM w/ a px fallback. A mixin for setting a sprite file location and basic setup for using with :before and much more.</p>
<p>Even if you use Compass or Bourbon I bet there's a time where you'd need something custom, just for your current project. Stick it in there and if you need to edit it. You'll know where it is.</p>
<h2 id="recap-%26-onwards" tabindex="-1">Recap &amp; Onwards</h2>
<p>In this post I've touched on what I include in my variables and mixins files. Helping me keep things sane and seperate in my Sass. In the next post I'll go over my _helper.scss and _debug.scss files where I make the HTML5 boilerplate helpers mixins so I can add them into my CSS and not my HTML (i'll get to my reasons why, soon).</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Structuring my Sass 101, part 2.</title>
      <link href="https://www.alwaystwisted.com/articles/structuring-my-sass-101-part-2.html"/>
      <updated>2013-01-07T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/structuring-my-sass-101-part-2.html</id>
      <content type="html">
        <![CDATA[
        <p>note: This is not a guide. This is just how I choose to do things.</p>
<h2 id="part-2%2C-compiling" tabindex="-1">Part 2, Compiling</h2>
<p>In the last post I quickly discussed my <a href="http://alwaystwisted.com/post.php?s=2013-01-07-structuring-my-sass-101-part-1">folder structure</a>, in this post I'm going to talk you through my basic set of files and how the yall compile to styles.scss.</p>
<p>So here's my folder structure -</p>
<p><img src="http://alwaystwisted.com/perch/resources/screen-shot-20130107-at-22.18.54-ck.png" alt="" loading="lazy" decoding="async"></p>
<p>Let's start with the main file that imports everything - styles.scss</p>
<h2 id="import-it-all-and-import-it-now" tabindex="-1">Import it all and import it now</h2>
<p>So the code within the styles.scss file looks like this</p>
<p>/*
-----------------------------------------------------
CSS file for cool client name here
Media: ALL THE THINGS</p>
<p>Author: Stuart Robson</p>
<p>-----------------------------------------------------
*/</p>
<p>// Normalize</p>
<p>@import 'defaults/_normalize.scss';</p>
<p>// Helpers</p>
<p>@import 'defaults/_helpers.scss';</p>
<p>// Mixins</p>
<p>@import 'defaults/_mixins.scss';</p>
<p>// Variables</p>
<p>@import 'defaults/_variables.scss';</p>
<p>// Grid System</p>
<p>@import 'partials/_grids.scss';</p>
<p>// Base</p>
<p>@import 'defaults/_base.scss';</p>
<p>// Put Your stuff here</p>
<p>@import '_page.scss';</p>
<p>// Internet Explorer Specific fixes</p>
<p>@import 'partials/_ie.scss';</p>
<p>// Print styles</p>
<p>@import 'defaults/_print.scss';</p>
<p>// DEBUG MODE</p>
<p>$debugMode:         false;</p>
<p>@import 'defaults/_debug.scss';</p>
<p>So, in this code you can see what I'm importing. There are a few things to note. The _helpers.scss is a set of @mixins that I currently have that I include into the compiled CSS rather than the HTML (that's a whole different blog post as to why).</p>
<p>There are two files that I keep in the 'partials' folder that are included in this 'master' import scss file. The _grids.scs file although 'generic' may have me putting things in specific to the site I'm working on as well as the default setup. Likewise the _ie.scss file, although always included in a project. I may decided to add specific IE CSS rules here (although this is rare now (another blog post).</p>
<h2 id="what's-on-the-_page" tabindex="-1">What's on the _page</h2>
<p>The _page.scss file (I might change that to _system.scss or something) is where I put any site specific scss files which would be taken from with the partials folder.</p>
<h2 id="recap-%26-onwards" tabindex="-1">Recap &amp; Onwards</h2>
<p>So I've touched on how I get my scss files importing with each other and compiling to a lovely styles.css file. Next up I'll go over my _mixins.scss and _variable.scss files with the whats and hows of the code therein.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Structuring my Sass 101, part 1.</title>
      <link href="https://www.alwaystwisted.com/articles/structuring-my-sass-101-part-1.html"/>
      <updated>2013-01-07T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/structuring-my-sass-101-part-1.html</id>
      <content type="html">
        <![CDATA[
        <p>note: This is not a guide. This is just how I choose to do things.</p>
<p>I've been meaning to write more about how I structure my Sass files when front-end dev'ing for clients. I was going to do this huge long post but I kept finding that idea daunting.</p>
<p>The plan is to have several short posts discussing bits of the whole that'll eventually make 'the whole'.</p>
<h2 id="part-1%2C-folder-structure" tabindex="-1">Part 1, Folder Structure</h2>
<p>I keep my Sass folder within my CSS folder. Using something like codekit you can choose to do this differently, but for me this is just easier.</p>
<p>So I'd have a CSS folder, where the compiled SCSS would end up, and a folder called SCSS. In that folder there's a further two, defaults and partials.</p>
<p><img src="/images/articles/screen-shot-20130107-at-22.12.43-ck.png" alt="folder structure" loading="lazy" decoding="async"></p>
<p>The 'defaults' folder is where I'd keep things that would never or very rarely change during the projects lifetime. This is where your reset would go, your print styles and your helpers.</p>
<p><img src="/images/articles/screen-shot-20130107-at-22.18.54-ck.png" alt="Sass folder fully open" loading="lazy" decoding="async"></p>
<p>In the image above there are two files that you'd probably have open for the start of a project and at times during it. These are the _variables.scss file and the _mixins.scss file (more on this in a future post).</p>
<h2 id="compiling" tabindex="-1">Compiling</h2>
<p>Hopefully you can see from the above image how everything gets compiled via styles.scss into styles.css (again more on this in a future post).</p>
<h2 id="recap-%26-onwards" tabindex="-1">Recap &amp; Onwards</h2>
<p>So, quite a short post. Just how I lay my folders and files out when I'm getting my pre-processing going on. In the next post of this little series I'll go through how and what I'm importing and where in the SCSS files to get my nicely outputted CSS up and running.</p>
<p><a href="http://alwaystwisted.com/post.php?s=2013-01-07-structuring-my-sass-101-part-2">Go to part two of this series</a></p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>monthly web services costs</title>
      <link href="https://www.alwaystwisted.com/articles/monthly-web-services-costs.html"/>
      <updated>2013-01-04T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/monthly-web-services-costs.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="shit%2C-how-much%3F" tabindex="-1">shit, how much?</h2>
<p>So, back in October <a href="http://twitter.com/chriscoyier">Chris Coyier</a> wrote a post <a href="http://css-tricks.com/web-developer-economics-monthly-service-costs/">laying out his monthly costs</a> for services he uses. I've been meaning to do this post in reply ever since. Now that I've started freelancing full time I thought it quite apt to write it.</p>
<h3 id="eukhost-ltd.---%C2%A38.99" tabindex="-1"><a href="http://www.eukhost.com/">EUKHost Ltd.</a> - £8.99</h3>
<p>I've been using EUKHost since 2006, I'm on an old legacy pricing structure on a shared linux server. It's pretty good, I've never noticed downtime and their status is generally 99.6% uptime. I've also (thus far) not broken it whilst being 'SmasingMag-ed' or 'Zeldman-ed'. It does me good, and it's cheap.</p>
<h3 id="github-(small-plan)---%C2%A34.40-(ish)" tabindex="-1"><a href="https://github.com/">GitHub</a> (small plan) - £4.40 (ish)</h3>
<p>Github hosts the code for rwdcalc.com but I also use it for creating private repos for client work as a kind of backup. I'm probably over thinking that bit. It's also privately hosting my boilerplate. A constant work in progress before release.</p>
<h3 id="browserstack---%C2%A312.14-(ish)" tabindex="-1"><a href="https://www.browserstack.com/">Browserstack</a> - £12.14 (ish)</h3>
<p>Unlike Chris, I do have a VM or two but sometimes it's just quicker to user Browserstack. Since it's recent UI update it feels faster and it works perfectly with localhost testing of site using mixture.io's content injecting for older browsers (no refresh needed for &lt;IE8).</p>
<h3 id="adobe-creative-cloud---%C2%A327.34-(ish)" tabindex="-1"><a href="http://www.adobe.com/uk/products/creativecloud.html">Adobe Creative Cloud</a> - £27.34 (ish)</h3>
<p>There was an email that I got giving me this real cheap for the first year if I upgraded from my Photoshop CS6 on-going payment. I couldn't say no. This means I've now got typekit tied to this payment rather than seperate.</p>
<h3 id="internet-access---%C2%A328.95-%26-%C2%A315.00" tabindex="-1">Internet Access - £28.95 &amp; £15.00</h3>
<p>I've got a broadband line in the house where I'm doing most of my work but I've also got a mifi for when I'm out and about and travelling. For £15 a month I get 10gb of mifi data access with Three. Pretty good coverage but when it drops whilst I'm commuting. Dang!</p>
<h3 id="freeagent---%C2%A316.20-(currently)" tabindex="-1"><a href="http://www.freeagent.com/?referrer=41kfq5bv">Freeagent</a> - £16.20 (currently)</h3>
<p>I'm not really sure if this 'fits' in this list. I think it does, it's a service that I pay for monthly and it's pretty important to me to help me 'keep my house' in order.</p>
<h2 id="to-total---%C2%A3113.02-(ish)" tabindex="-1">To Total - £113.02 (ish)</h2>
<p>Adding all that up works out at £113.02 (ish) a month. Less than I was expecting at almost half of that is internet access (quite vital).</p>
<h2 id="share" tabindex="-1">Share</h2>
<p>Like Chris states in his post, it'd be nice to hear what your costs are and why you 'need' it to work each month.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Another turning point, a fork stuck in the road.</title>
      <link href="https://www.alwaystwisted.com/articles/another-turning-point-a-fork-stuck-in-the-road.html"/>
      <updated>2012-12-21T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/another-turning-point-a-fork-stuck-in-the-road.html</id>
      <content type="html">
        <![CDATA[
        <p>Day One.</p>
<p>This is it I guess. My first day of 'properly' freelancing.</p>
<p>Let's see how this goes.</p>
<p>To paraphrase Green Day, I hope I have the time of my life.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Get in the mix</title>
      <link href="https://www.alwaystwisted.com/articles/get-in-the-mix.html"/>
      <updated>2012-12-09T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/get-in-the-mix.html</id>
      <content type="html">
        <![CDATA[
        <p><img src="/images/articles/mixture-ck.gif" alt="mixture logo" loading="lazy" decoding="async"></p>
<p>So there's been quite a flurry of tweets tonight about <a href="http://mixture.io">Mixture</a>. I'm sure you'll know if you follow me on twitter I frickin' love it. So in this brief post I hope to explain how it helps me.</p>
<h2 id="the-obligatory-back-story" tabindex="-1">the obligatory back story</h2>
<p>So, I'm a front-end developer. I don't design. I rarely dare touch anything to do with that 'back-end' (insert Kenneth Williams gif here). I generally take a clients designs and make them look bloody gorgeous across a bounty of devices at a plethora of speeds, but I digress.</p>
<h2 id="team-mixture" tabindex="-1">Team Mixture</h2>
<p>I've been using Mixture for the last 5-6 weeks (of evenings) for a client site. It's not the biggest site in the world but it'd be fairly sizeable once what I'm coding gets plumbed into the 'back-end' (another gif) and all the content is added in.</p>
<p>{please note: Mixture is not a code editor).</p>
<h2 id="html%2F.liquid-craziness" tabindex="-1">HTML/.liquid craziness</h2>
<p>So with Mixture I've managed to do something I think is amazing. I've managed to<br>
create 'bits' of HTML that I can then tie into different pages of the site as and when needed. I can override parts of the page with other 'bits' so I can write once, use anywhere on a site I'm developing. That's pretty speedy. It's really easy to refactor, edit and make your code better across a whole site in a blink of an eye.</p>
<p><a href="http://docs.mixture.io/templates">Docs for Mixtures templating awesomeness</a></p>
<h2 id="sass%2Fless%2Fstylus" tabindex="-1">Sass/LESS/Stylus</h2>
<p>I love me some pre-processing. Mixture tries to cater for all allowing you to write your CSS dry, with Sass, LESS or Stylus. That's pretty open. It also includes Compass and Bourbon so Sass/SCSS users are well catered for. Allowing me to choose what language I want to pre-process in is pretty nice rather than 'being told'. Not a CSS pre-processor but Mixture also allows from CoffeeScript too.</p>
<p><a href="http://docs.mixture.io/preprocessors">Docs for Mixtures pre-processor funtimes</a></p>
<h2 id="optimisation" tabindex="-1">Optimisation</h2>
<p>Image optimisation, debugging and CSS/JS minifying is built in.</p>
<p>Docs on Optimisation</p>
<h2 id="boilerpates" tabindex="-1">Boilerpates</h2>
<p>Opening up Mixture allows you to create a project. This could be blank but what's great is that it includes so boilerplates/frameworks to get you going. It's got a Compass boilerplate. Inuit.css from Harry Roberts, the Twitter Bootstrap and soon (I think) you'll be able to add your own to get you going even quicker.</p>
<h2 id="to-do" tabindex="-1">To-Do</h2>
<p>So I'm coding a part of a page and I do something I want to get back to. Mixture has a todo built in. I can place a 'todo' on any page and the app keeps a tally and allows me to 'jump to' a todo from within in it. That's great if you need to quickly use a 'magic number' for something or want to press on and come back to it later. The todo part of the app is excellent.</p>
<h2 id="local-host" tabindex="-1">Local Host</h2>
<p>'Out of the box' Mixture has created a virtual host server for my project. I can edit some details in a file (easily) and be able to access the project Mixture is running on all my devices. That's pretty good for testing on not only other browsers (IE for example) but also devices.</p>
<h2 id="'staging'-server" tabindex="-1">'staging' server</h2>
<p>Mixture also creates a 'staging' server so that you can upload what you're working on. This is awesome for client approval, checking etc. My client can now open the Android phones browser and check out how their site is looking, how's it coming along. You could even use this for demo-ing ideas you have for certain aspects, like a mobile navigation pattern.</p>
<h2 id="live-reload-'all-the-things'" tabindex="-1">Live Reload 'all the things'</h2>
<p>LiveReload is baked in and the team at Mixture have bettered it so that it works on ALL* browsers including good ol' Internet Explorer 6, 7, 8, 9 and on any Android stock browser. I've done this with my Air, iPhone (chrome iOS), Nexus 7 (Opera Mobile) and Huawei Blaze (Android 2.3 stock browser). That's great to help you quickly test, locally, how you site'd look with your device test suite/lab.</p>
<p>*except Opera mini, because, you know...</p>
<p>Here's a video from Neil <a href="http://www.youtube.com/watch?feature=player_embedded&amp;v=yOM2_UATlWw">testing out 'live reload' on some devices that do and don't support LiveReload</a>.</p>
<p><a href="http://docs.mixture.io/mixture">Docs for boilerplates, todo, local and online settings</a></p>
<h2 id="exports-to-html" tabindex="-1">Exports to HTML</h2>
<p>Yep, does that. So all you @includes, ifs and everything get 'compiled' into a full on static site.</p>
<h2 id="justice" tabindex="-1">Justice</h2>
<p>I've probably not done the product justice, but it's awesome.</p>
<p>If you've not signed up <a href="http://mixture.io/">then do it</a> (insert my favourite gif here). If you've a question I guess you'd best ask <a href="http://twitter.com/neiltak">Neil</a>, you could ask me but I'm sure I'm only touching the surface of it's power.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>What and how I support browsers</title>
      <link href="https://www.alwaystwisted.com/articles/what-and-how-i-support-browsers.html"/>
      <updated>2012-10-23T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/what-and-how-i-support-browsers.html</id>
      <content type="html">
        <![CDATA[
        <p>I was perusing the twitters today, as I do, and came across a tweet about the twitter bootstrap framework and it's support (or lack of) for Microsoft's internet explorer. This got me wanting to write this post but there's also another reason why I'm about to blabber on about support (which I hope you'll read).</p>
<h2 id="january" tabindex="-1">January</h2>
<p>If you've <a href="http://www.twitter.com/sturobson">followed me on twitter</a> or we've spoken, you'll know that I'm 'giving up' client work until January 2013 so I can re-adress where I want to be, what I want to do and by when I want to get thing s rolling.</p>
<p>Hopefully in January 2013 I'll have a new version of this site with more 'about me/hire me' shizzle to 'drum up some trade', a new design of RWDCalc will be out, I hope to have something happening with deCSSor and all will be good.</p>
<p>On my process to get there I think it'd be a good idea to document some bits on the way. I guess this'll be the first one.</p>
<h2 id="i-digress-(i-do-that)" tabindex="-1">I digress (I do that)</h2>
<p>So, browsers &amp; the support thereof. Weekly? Daily? Hourly or at least sometimes I see conversations regarding browser support and phrases like 'we don't support IE7 but support IE8 and up' or similar. At face value such a phrase doesn't mean anything (I feel).</p>
<p>You don't support IE7 so they just get a blank page?</p>
<p>If so, that's ridiculous.</p>
<p>If you code sites correctly there's a chance that it'll be useabe in quite a few browsers and there in lies the need for clarification of the word 'support'.</p>
<h2 id="support" tabindex="-1">Support</h2>
<p>If you stipulate what browsers you 'support' you need to define that level of 'support'. Pixel perfection? It'll look a little different but it'll work the same? There'll be a couple of sections that won't work for a certain browser but you do this to rectify it and so on.</p>
<p>As we know the answer to <a href="http://dowebsitesneedtolookexactlythesameineverybrowser.com/">'Do websites need to look exactly the same in every browser?'</a> the interaction doesn't have to be the exactly same either, does it. If I'm supporting mobileSafari and Opera mini do I have to have a flyout menu for both browsers? I'd say no. As Opera mini is a proxy browser and is tied down with what JS can be done with it perhaps give Opera mini a nav at the bottom of the 'page' or just under the heading instead of something that'd rely on JS that'd reload the page.</p>
<h2 id="definitions" tabindex="-1">Definitions</h2>
<p>Of course, with all things, I'd say this is project dependant too. I don't think you can be so cut and dry to your clients and there users to say 'I don't support browser X' especially if current usage is browser X. You should define the support you'd provide to that browser and it's users for the specific client.</p>
<h2 id="additional-costs" tabindex="-1">Additional Costs</h2>
<p>If you're finding yourself required to support older browsers that'll take 'a while' to get working as needed then charge accordingly. Something like a 'I support browsers X, Y and Z anything else is to be negotiated and quoted before the contract is signed and agreed upon'.</p>
<h2 id="so-you're-saying-support-ie6" tabindex="-1">So you're saying support IE6</h2>
<p>No, I'm just saying decide what browsers you are going to support and define the level of support for those devices as a base to start with and adapt for each client and their respective requirements.</p>
<h2 id="my-level-of-support%3F" tabindex="-1">My level of support?</h2>
<p>This is currently undecided, but I'd could probably say for certain that it'd be from IE8 and up, the latest Chrome/Safari/Firefox/Opera browsers on 'desktop' and then the browsers found on 'mobile devices' to be confirmed and part of me blathering on here is for me to start thinking about it. So, in January I'll hopefully know.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A responsive &quot;accordian to tabs&quot; pattern</title>
      <link href="https://www.alwaystwisted.com/articles/a-responsive-accordian-to-tabs-pattern.html"/>
      <updated>2012-10-14T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-responsive-accordian-to-tabs-pattern.html</id>
      <content type="html">
        <![CDATA[
        <p>Back in August I was working for a client who 'got me on board' to deal with a variety of things one of which being the creation of some code that would turn a list of content from an accordian to some tab-ed content.</p>
<p>Along with a little help from stack overflow I managed to squeeze the workings out of jQuery and CSS so that dependant on viewport size the user would see an accordian of content or a tab navigation-ed content.</p>
<p>It worked great.</p>
<p>Some months later that man from Pittsburgh the webhead <a href="http://twitter.com/brad_frost">Brad Frost</a> created <a href="http://bradfrost.github.com/this-is-responsive/">This Is Responsive</a> a site on github containing links to resources, news and patterns around the ever growing subject of web design. I was going through this list to find that he'd included 'accordian to tab' as a pattern that hadn't been created yet.</p>
<p>I thought it'd be great to give something back to 'the community' rather than holding something like this to close to my chest. So over the last week I got to working on tidying up the code I created. I cleaned out the Samuel L. Jackson offensive quotes and replaced it with lorem ipsum and took the styling to something as simple as possible.</p>
<p>This is the result.</p>
<p>This is great for people to work from as a starting point, but there a few things that I'd like to eventually change. I'd love to get rid of dependancy on jQuery to get the show/hide to work so that it would hopefully run a little smoother on mobile as the processor won't have to work on the JavaScript framework as well. To that end I'd love to add animations to it via CSS3 rather than jQuery or JavaScript so that it's more 'progressively enhanced'. I'd also like to check the accessibility of it fully to make sure it works as well as it possibly can for as many circumstances that it could be found in.</p>
<p>I hope you like it, I hope you use it, I wish you'd break it and fix it too.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>My process is broken and that&#39;s ok.</title>
      <link href="https://www.alwaystwisted.com/articles/my-process-is-broken-and-thats-ok.html"/>
      <updated>2012-10-13T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/my-process-is-broken-and-thats-ok.html</id>
      <content type="html">
        <![CDATA[
        <p>It seems everyone is talking about process at the moment, whether it's broken or not. Since I've been playing with HTML, then CSS etc etc my process has adapted. From being taught in college to draw out the site map before anything else (back in 1998) everytime I've come to create a site be it designed and developed by myself or, more recently, designed by others to be coded and 'responsified' by myself I change 'bits' of how I work.</p>
<h2 id="disclaimer." tabindex="-1">Disclaimer.</h2>
<p>I can't tell you really what they are, I don't write enough things down.</p>
<p>But I'd say my process is broken, it will never be perfect. <a href="http://www.youtube.com/watch?v=HbR7axof1wk">Life moves pretty fast</a> for the chance to have a correct, 100% working process because I'm always learning and trying new things.</p>
<h2 id="always-be-changing." tabindex="-1">Always Be Changing.</h2>
<p>And, I'm happy with that. It works, it could be better, but it works, for me and clients I have work(ed) with/for. Some tools and ways or working continue project to project, possibly being refined, so slightly, each time. Things like pre-processors and how I use them have forever been in a state of flux since i first started using LESS and more recently moving to Sass/SCSS.</p>
<h2 id="adaptability." tabindex="-1">Adaptability.</h2>
<p>I can't tell you how to change your process, I can't tell the best way to do something in your process. It's your process, used by you. Who, unsuprisingly, is not me. I can suggest just the one thing.</p>
<p>Adapt.</p>
<p>After a project your next project goes out the door sit back, think of all the things that helped and all the things that hindered that project. Write them down (I'm doing this as soon as my client's client gives me things to finish). Think of what you can change, add or subtract to the process you've just gone through to make it better.</p>
<p>Client communication, design sign off, boilerplate starting files, CSS commenting, SCSS mixins, HTML/HAML templates, Photoshop editing, local enviroment development, pushing it to the server, version control and much more. There's bound to be something in your process that you can find that needs adapting, figure how you can make it better and do it, rinse and repeat.</p>
<p>Do it.</p>
<p><img src="/images/articles/benstillerdoit-ck.gif" alt="do it." loading="lazy" decoding="async"></p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Content, first?</title>
      <link href="https://www.alwaystwisted.com/articles/content-first.html"/>
      <updated>2012-10-13T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/content-first.html</id>
      <content type="html">
        <![CDATA[
        <p>We don't need all the words in the world to start building (responsive) websites. Part of the joy of (responsive) web design is that we should have ease in responding to changes in perceived content.</p>
<h2 id="potted-paragraphs-of-history" tabindex="-1">Potted paragraphs of history</h2>
<p>In March 2005 <a href="https://twitter.com/jasonfried">Jason Freid</a> wrote a post on <a href="http://37signals.com/svn/archives/001083.php">the 37 Signals blog</a> damming 'lorem ipsum' and saying that we should '&gt;use real and relevant words not “lorem ipsum” representative text'. Then, in 2009, the <a href="http://blog.contentmanagementconnection.com/Home/20016">Content Management Connection blog</a> wrote a post that exclaimed we should be taking to create sites from the content up. Rather than painting pretty pixels with lorem ipsum we should be working with the words first before 'colouring it in'.</p>
<p>That post links back to one from 2007 by <a href="https://twitter.com/justinkistner">Justin Kistner</a> which talks about <a href="http://www.justinkistner.com/archive/content-driven-design/">Content Driven Design</a> where he talks about the box-model of the web page influencing constraints on content and helping to define it's structure. In 2008 <a href="http://twitter.com/zeldman">Jeffrey Zeldman</a> created a post on his blog with a tweet - <a href="http://www.zeldman.com/2008/05/06/content-precedes-design/">'Content precedes design. Design in the absence of content is not design, it’s decoration.'</a></p>
<p>Jump forward to 2011 and <a href="http://twitter.com/adactio">Jeremy Keith</a> in a post where he hammers <a href="http://adactio.com/journal/4523/">'home the point that it's all about the content.'</a></p>
<h2 id="content%2C-content%2C-content" tabindex="-1">Content, content, content</h2>
<p>I'm sure I've missed some parts here, but you get the point. Web design is all about the content. But what if you don't have the content? What if you're unfortunate to not have a client that can provide all the words you need before you start? Do you hold off until it's done and not eat? I think that's (obviously) ridiculous.</p>
<p>Some of us aren't fortunate enough to get every last bit of content when we get a project. Some clients just can't work like that. Some clients just won't work like that. Some clients are busy running their business and think it's your role as the web designer (which it is, if you've spec'd it in the agreed quote and project brief).</p>
<h2 id="structured-content" tabindex="-1">Structured content</h2>
<p>Recently I've been thinkin that you can still design your sites without actual content. All you'd need is the knowledge of what content there will be and then structure these 'content blocks' so they 'work' across mulitple devices.</p>
<h2 id="content-blocks" tabindex="-1">Content blocks</h2>
<p>Let's take the most used example of a blogpost and look at the 'content blocks' that it would have.</p>
<p>As you can see you could separate the heading, date, author, first paragraph, article heading, and 'the rest'. These are the content blocks that could make up a blogpost.</p>
<p>I think you can design with these content blocks and you don't neccesarily need the 'actual' content to get to work.</p>
<h2 id="but-designing-blogposts-are-easy" tabindex="-1">But designing blogposts are easy</h2>
<p>Ok, so let's talk about something else. How about a product page for ecommerce site that sells kettles? For this we're only going to focus on the the actual product bits, not the header, navigation or footer.</p>
<p>So first off, we would have a 'the product title'. Then maybe, as it's for an ecommerce site you'd have a price, a brief list of product details, a call-to-action 'buy' button, some social buttons so users can tell their friends they're buying it, a bigger description of the product, a more thorugh list of product details, a product code, a print button and so forth.</p>
<p>So you could start designing the layout and the paint of the page knowing what content blocks are neede and not neccesarily knowing the content.</p>
<h2 id="a-consideration" tabindex="-1">A consideration</h2>
<p>To do something like this would need a change in process. You'd need reiteration on the content blocks over the time of design and development of the site/app. With responsive web design this is now (in my opinion) easier than ever as you should be in a statle of 'agile' development.</p>
<p>Of course, this works for me but it could mean it's likely that it might not work for you. You may have all the content first, you might work on your own stuff and not need the content as 'you know' what it'll be.</p>
<h2 id="still-get-your-content-as-soon-as-possible" tabindex="-1">Still get your content as soon as possible</h2>
<p>I'm not writing this to convince that 'content first' shouldn't be taken as seriously as people have written or spoken about. It is. But if you're waiting on it you can get some work done in the mean time, but still strive to get the content as soon as is possible into your work.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>These 3 lines</title>
      <link href="https://www.alwaystwisted.com/articles/these-3-lines.html"/>
      <updated>2012-10-12T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/these-3-lines.html</id>
      <content type="html">
        <![CDATA[
        <p>Back in March, that Andy Clarke wrote a post on the need for a <a href="http://stuffandnonsense.co.uk/blog/about/we_need_a_standard_show_navigation_icon_for_responsive_web_design">'standard' icon for navigation</a> in responsive web design. Two month's later in May, when I found my blogging 'mojo', I wrote a post on making <a href="../post.php%EF%B9%96s=2012-05-12-create-a-pure-css-menu-button.html">navigation icons with only CSS</a>. Then some months later Jeremy Keith wrote an article on three lined <a href="http://adactio.com/journal/5666/">'navicons'</a> and two days later Tim Kadlec took a similar approach to mine and created a <a href="http://timkadlec.com/2012/08/mobile-navigation-icons/">better CSS version</a> of the three lines icon using nice and responsive ems.</p>
<p>This week Jordan Moore (not the country singer) wrote a post on '<a href="http://mobile.smashingmagazine.com/2012/10/08/the-semantic-responsive-design-navicon/">The semantic, Responsive Navicon</a>' and a couple of days later the trickster Chris Coyier wrote a post that showed various ways to have the <a href="http://css-tricks.com/three-line-menu-navicon/">three lines as a responsive navicon</a>.</p>
<p>After Jordan's post, there was a brief <a href="https://twitter.com/brad_frost/status/255293924472680448">discussion on twitter</a> on the use of the icon and 'it depends'. So I thought I'd quickly throw down some thoughts on what I think.</p>
<p>So, here goes.</p>
<h2 id="icon" tabindex="-1">Icon</h2>
<p>I think the icon is great, I think the fact that a site that has <a href="http://www.bbc.co.uk/news/technology-19816709">over a billion users</a> of which just under <a href="http://www.socialbakers.com/blog/554-facebook-hits-488-million-mobile-users-infographic">half access via mobile</a> which (possibly not for all devices) uses the icon helps. A lot. Yes, Facebook's site is more 'app-like' than your common or garden, um, garden centre website but I'm sure (at a wild guess) those users will recoginise it on the website you've created for your client.</p>
<h2 id="words" tabindex="-1">Words</h2>
<p>I also think that if you've decided to go with the three lines including the word 'menu' is just a little bit of extra bulk you don't need. Let's not forget that space on a narrow viewport is at a premium, you could be taking up precious white space by 're-affirming' what the icon is doing. So I would suggest one or the other. Not both. As well as my feeling towards the added 'bulk' it's not very all encompassing in the World Wide Web.</p>
<h2 id="for-instance..." tabindex="-1">For instance...</h2>
<p>menu is four charecters, in Icelandic the word is Valmynd. That's three extra charecters taking up room, breaking your site, making it look crappy.</p>
<h2 id="opinion" tabindex="-1">Opinion</h2>
<p>Of course, this is just my opinion. There are many opinions like it, but this one is mine. If I was to use an icon for navigation on a narrow viewport I would use three lines with no wording.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Coda 2 wish list</title>
      <link href="https://www.alwaystwisted.com/articles/a-coda-2-wish-list.html"/>
      <updated>2012-09-17T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-coda-2-wish-list.html</id>
      <content type="html">
        <![CDATA[
        <p>So, if you've been following along my twitter account you would have seen I've started to use Coda 2 as my main code editor for all the fun HTML, CSS and JavaScript I get to do. I started using Coda when I got my first Mac in 2009 after years of using Dreamweaver (ever since version 3). I had a dalliance with Espresso 2 for 6 months and wasn't to keen on what I saw of Coda 2.</p>
<p>Then I decided to try it for a client project. To see how I go along.</p>
<p>Since using it daily for quite a while now I've, every now and then, found some things that'd I really like to be added to the upcoming updates which I think will make such a great product even better.</p>
<p>This list is in absolutely no particular order and I may add to this post as and when I ever think of them.</p>
<h2 id="a-project-todo-list" tabindex="-1">A project todo list</h2>
<p>You've got your current project open. Maybe there's the HTML and CSS page open. You think of something that you need to add on a todo list for the project. Wouldn't it be great if you can do that somewhere within Coda? You could have it as an option in the sidebar. Having the todos for a project tied to the project rather than a third party would, I feel, speed up your work and aid your concentration. Rather than flitting from Coda to a todo app to Coda again.</p>
<h2 id="the-sidebar-open%2Fclosed-per-file." tabindex="-1">The sidebar open/closed per file.</h2>
<p>Currently I'm finding I use the sidebar when I'm editing the CSS but don't want it there when I'm playing my HTML. It'd be great if, somehow, The sidebar would remember it's open or closed state on a per file basis rather than per project. I'm sure if I still and my 27' iMac instead of this 13' MBA I'd have The sidebar open all them time though. But it'd be a great option.</p>
<h2 id="add-markdown-files-as-a-book." tabindex="-1">Add Markdown files as a book.</h2>
<p>When I'm writing my CSS with LESS I'm more often than not using Clearleft's ClearLESS LESS library made by // All Marked Up //. This library has a fantastic markdown file of all the what's and wherefores to help and it'd be great if I could have this nicely accessible in say the Books format in Coda. So I can have it open and easily readable.</p>
<h2 id="add-a-viewport-dimensions-helper-to-the-preview" tabindex="-1">Add a viewport dimensions helper to the Preview</h2>
<p>Although, yes, I do 'design in the browser' and test on a variety of devices I find myself using the preview in Coda quite a lot for initial layout and colouring in. Sometimes I use the built-in iOS 'user agents' but when I don't it's because I'm resizing the 'browser'. It'd be great to have an option to include a live dimensions of the viewport. Like Dave Rupert's fantastic FitWierd.</p>
<h2 id="a-key-and-mouse-shortcut-for-'jump-to-style'" tabindex="-1">A key and mouse shortcut for 'Jump to Style'</h2>
<p>Still using Preview, I really like the idea of being able to go to the line of CSS for a particular element from looking at the rendered page. Rather than (or as well as) having it as a right-click menu option I'm sure it'd speed up development if it was (also) a mouse(trackpad) and keyboard shortcut. Something like shift + cmd + click so that I can quickly get to CSS code. Of course this could prove tricky as some elements have more than one class etc but maybe the mouse/key shortcut could open up the options of CSS available. I'm sure that'd be a little quicker than right-click, move the mouse down, across and select.</p>
<h2 id="jump-to-style-goes-to-open-less%2Fsass-file" tabindex="-1">Jump to Style goes to open LESS/Sass file</h2>
<p>As I've mentioned in wish number 3. I use LESS, I also use Sass (well the SCSS syntax). If in my project I've got a Sass or LESS file open I'd love the Previews 'Jump to Style' to be able to go to those files rather than my compressed one line of CSS which I can't read.</p>
<h2 id="only-view-certain-types-in-the-navigator" tabindex="-1">Only view certain types in The Navigator</h2>
<p>Sometimes I add bookmarks to my CSS so I can jump to them quickly. It'd be really good if, in The Navigator, I could just view the bookmarks for the file that's open rather than all the CSS classes (for example) as well. You can arrange all the bits that Navigator by kind or Name. I'd really love to be able to only see certain types (like bookmarks).</p>
<h2 id="move-the-'iphone'-about" tabindex="-1">Move the 'iPhone' about</h2>
<p>When I'm using the Preview mode I sometimes have the iPhone 'user agent' set. It'd be really nice if I click to inspect element I could move the 'iPhone' so that I can easily view the webkit inspector (granted this would not be an issue on a 27' iMac).</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Slightly Bizarre goings-on #1</title>
      <link href="https://www.alwaystwisted.com/articles/slightly-bizarre-goings-on-1.html"/>
      <updated>2012-09-01T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/slightly-bizarre-goings-on-1.html</id>
      <content type="html">
        <![CDATA[
        <p>If you've <a href="http://twitter.com/sturobson">followed me on twitter</a> over the last couple of days, you may have seen some mad panic as I managed to b0rk this sites <a href="http://grabaperch.com/">Perch CMS</a> installation. I managed to roll back to v1 of the CMS last night and have been itching to write a post since.</p>
<p>Having recently read <a href="http://css-tricks.com/chronicle-i/">Chris Coyiers</a> post and just moments ago see that <a href="http://pauladamdavis.com/blog/2012/09/memoirs-of-a-coder-1/">Paul Adam Davis</a> has started a 'weekly update' kind of post too. I thought it was a great idea. Hopefully this'll help you and me. I'll be adding great things I find (which hopefully'll help you) and just bumbing on about how my week has been (which may aid my faultering memory).</p>
<h2 id="slightly-bizarre-%3F" tabindex="-1">Slightly Bizarre ?</h2>
<p>When I was in 'a rock band' our first gig got a review in a local weekly magazine. The words 'Always twisted, slightly bizarre' were used when referring to my guitar riffs. Those four words have stuck with me since then (2002). I've finally found a home for 'slightly bizarre'</p>
<h2 id="what's-been-going-on." tabindex="-1">What's been going on.</h2>
<ol>
<li>I'm still writing my 8/9/10+ part series on resposnive web design for WebTutsPlus. I'm hoping to have the first two articles out the door in the next week or two.</li>
<li>I'm currently working on the smallest, biggest client site ever.</li>
<li>I've splurged some cash on <a href="http://2013.newadventuresconf.com/">New Adventures</a>, <a href="http://2012.webdevconf.com/">Web Developers Conference</a> and <a href="http://www.handheldconf.com">Handheld</a> conference tickets.</li>
<li>I've been playing with <a href="http://jsfiddle.net/sturobson/jrTcg/">a little accordian &gt; tabs bit of code</a> for a clients site which I want to improve.</li>
<li>This blog has loads of drafts that need completing, when I have the time.</li>
<li>I'm about 40% at my 'go freelance' savings.</li>
</ol>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Sass mixin for media queries and IE</title>
      <link href="https://www.alwaystwisted.com/articles/a-sass-mixin-for-media-queries-and-ie.html"/>
      <updated>2012-08-06T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-sass-mixin-for-media-queries-and-ie.html</id>
      <content type="html">
        <![CDATA[
        <p>I'm currently finishing up some front-end co-coding for a client who hired me for all the mobile/responsive goodness. As well as this they wanted me to instigate and create the CSS using Sass/SCSS. Near the end of the project they asked how we would support IE8/7/6.</p>
<p>We did discuss this at the start of the project but carried on with 'all the things'. I had seen all the hotness around <a href="http://thesassway.com/intermediate/responsive-web-design-in-sass-using-media-queries-in-sass-32">Sass 3.2</a> that would allow you to create a <a href="https://gist.github.com/1493930#file_style.scss">respond-to mixin</a>. So decided to upgrade my Sass gem to the <a href="http://rubygems.org/gems/sass/versions/3.2.0.alpha.278">latest version</a> and updated all my 'hand coded' media queries with the relevant Sass/SCSS mixins.</p>
<p>This was great, kinda, it now took the px/em value out of the CSS and allowed me to change it in my Sass settings/mxins/variables file but it did not let me create a fallback for internet explorer.</p>
<p>Here is the SCSS and the CSS I wanted/expected.</p>
<h3 id="the-scss-setup" tabindex="-1">The SCSS setup</h3>
<p>// Setting up a quick respond-to mixin
@mixin respond-to($name) {
@if $name == tablet {
@media only screen and (min-width: 768px) { @content; }
}
}</p>
<p>// So this is the mixin that I'm currently using</p>
<p>@mixin this-is-what-i-want($name. $ie-class) {
ie-class-here { @content; }
media-query-here } @content; }
}</p>
<h3 id="the-scss-file" tabindex="-1">The SCSS file</h3>
<p>// This is how I include the mixin within my SCSS file</p>
<p>.foo {
margin: 0 auto;
padding: 0 10px;§</p>
<p>@include this-is-what-i-want(tablet, lt-ie9) {
min-width: 940px;
max-width: 1220px;
padding: 0 20px;
}
}</p>
<h3 id="my-'wished-for'-css-output" tabindex="-1">My 'wished for' CSS output</h3>
<p>.foo {
margin: 0 auto;
padding: 0 10px;§
}</p>
<p>.lt-ie9 .foo {
min-width: 940px;
max-width: 1220px;
padding: 0 20px;
}</p>
<p>@media only screen and (min-width: 768px) {
.foo {
min-width: 940px;
max-width: 1220px;
padding: 0 20px;
}
}</p>
<h3 id="to-the-internets" tabindex="-1">To The Internets</h3>
<p>So I started crawling the <a href="http://gist.github.com/">gists on gitub</a> to see if anyone had created a little code snippet just for this reason. I didn't. There was nothing. So I quickly asked some really, clever and amazing people on the twitters and I got this bit of code from the fantastic <a href="http://twitter.com/snugug">@snugug</a>.</p>
<p>mixin respond-wrapper-fallback($name, $wrapper-class) {
.#{$wrapper-class} &amp; {
@content;
}
@include respond-to($name) {
@content;
}
}</p>
<p>This now turns my 'wished for' CSS output into a reality and now means I can create a fallback for Internet Explorer from 'whatever' CSS Media Query block I need.</p>
<h2 id="to-skin-a-cat." tabindex="-1">To skin a cat.</h2>
<p>There's more than one solution for patching up code for Internet Explorer using Sass. This is the solution I required. <a href="https://en.twitter.com/jaffathecake">Jake Archibald</a> created a <a href="http://jakearchibald.github.com/sass-ie/">IE-friendly mobile-first solution</a> which I shall be likely to use at the start of future projects and there's <a href="http://nicolasgallagher.com/mobile-first-css-sass-and-ie/">Nicolas' solution</a> also.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Books For Sale</title>
      <link href="https://www.alwaystwisted.com/articles/books-for-sale.html"/>
      <updated>2012-08-05T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/books-for-sale.html</id>
      <content type="html">
        <![CDATA[
        <p>Ok, I'm selling these books. The prices are a guide and they include P&amp;P.</p>
<p>If you want to buy any of these, <a href="http://twitter.com/sturobson">let me know via twitter</a> or via email - <a href="mailto:stu@alwaystwisted.com?subject=books%20for%20sale...">stu@alwaystwisted.com</a></p>
<p>Payment is expected to be completed via bank transfer (paypal is a last resort though).</p>
<p>A Practical Guide to Information Architecture - £20</p>
<p>A Practical Guide to Designing with Data - £20</p>
<p>The Mobile Frontier - £20</p>
<p>Writing For The Web - £8</p>
<p>HTML5 and CSS in the real world - £15</p>
<h2 id="the-original-list" tabindex="-1">The original list</h2>
<p>CSS Mastery (2nd edition) - £8</p>
<p>Bulletproof Web Design (2nd edition) - £6</p>
<p>CSS The Missing Manual - £7</p>
<p>practical information article - £6</p>
<p>Content Strategy for the web (1st edition) - £9</p>
<p>Beginning iPhone 3 development - £7</p>
<p>Everything you know about CSS is wrong! - £7</p>
<p>Principles of beautiful web design (1st edition) - £7</p>
<p>Sexy Web Design - £8</p>
<p>PHP, MySQL and Apache All in One - £12</p>
<p>Accelerated DOM Scripting with Ajax, APIs and Libraries - £6</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Just a little cog...</title>
      <link href="https://www.alwaystwisted.com/articles/just-a-little-cog.html"/>
      <updated>2012-07-22T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/just-a-little-cog.html</id>
      <content type="html">
        <![CDATA[
        <p>If you've been following me on the twitters recently you may have seen the odd tweet about me 'getting ready' for the world of full time freelance front-end development. I'm currently only 'coding by candlelight' in the evenings whilst holding down a day job (which is completely the opposite to anything which involves a computer).</p>
<p>I've slowly started getting some work, good work. I'm saving what I can. You see, working 9-5 and being a family man whilst trying to carve out a freelance career in web design/development means my hourly working week as a night-owl is quite small. Although I do my best, catching five minutes here and there as well as evening shifts of up to 4 hours I can pull in about a 20 hour week. But I'm digressing about the point of this post.</p>
<h2 id="i'm-not-jack." tabindex="-1">I'm not Jack.</h2>
<p>When I started 'playing' with the web it was all tables and spacer.gifs. Fun days, 'easy' days. Now we've got all these little niches within the industry I don't think we really classified back then. I was a 'web designer' (not a site manager) I'm now a 'front-end developer'. I try and concentrate my efforts on HTML, CSS and JavaScript. I can't really design for toffee but I love getting my hands filthy with code. I don't know much about PHP. I'm not a Jack of all trades but an attempted master of 3.</p>
<h2 id="but-it's-not-that-easy." tabindex="-1">But it's not that easy.</h2>
<p>Although I concentrate on what I like to refer to as creating the 'code that makes the page you use' there's more to it now than just 'holy trinity' of HTML, CSS and JavaScript. Trying to be a little cog, a cog that'd fit perfectly into your project I try to adapt. I'm not made out of steel iron, I'm malleable.</p>
<p>I'm starting to think that really, you have got to be 'adaptable'. I'm currently working for a client that uses Sass (well SCSS) which I tried around Christmas last year <a href="https://twitter.com/sturobson/status/118756553166823424">but</a> I ended up going straight to LESS as, for me, it worked out of the box. So <a href="http://alwaystwisted.com/post.php?s=2012-07-08-stu-goes-sass">I'm learning Sass/SCSS</a> not only to work with this client but to make myself more knowledgeable and adaptable for future clients. If I know <a href="http://www.youtube.com/watch?v=tScm-eZInBE">this, that and the other</a> I'll be a better fit for a client and I want to be a better (if not perfect) fit, surely that'd get me work, right?</p>
<h2 id="%23teamweb" tabindex="-1">#teamweb</h2>
<p>So as part of being this little cog I get fed up. It shouldn't be about winning and losing at something such as pre-processors. For me, wanting to 'find my feet' (and more work) I think you should know as much as you can possibly fit in your head. Don't stick with what's the most popular, easiest to implement. Try everything once (well not everything *coughs*), if at first you don't succeed, try, try, try again. Learning what you can and as much of it as you can would make you a more rounded front-end developer able to pick up something you have a hand on and make beautiful.</p>
<p>You may think from my recent tweets that I'm edging to #teamsass but the redesign of this site will be using LESS. I gotta keep the cog whirring, playing with stuff, learning, adapting, creating awesomeness.</p>
<h2 id="back-to-the-future!" tabindex="-1">Back to the future!</h2>
<p>So I apologise for a little rambling, but I just needed to get this down. I'm looking forward to and hoping to make 'the leap' soon and I think being able to 'adapt' to my clients needs as a front-end developer is important. So if you're looking for a malleable front-end developer in the next few months, <a href="mailto:stu@alwaystwisted.com?subject=A%20maleable%20request">hit me up</a>.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A case for some Accessibility in our CSS</title>
      <link href="https://www.alwaystwisted.com/articles/a-case-for-some-accessibility-in-our-css.html"/>
      <updated>2012-07-21T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-case-for-some-accessibility-in-our-css.html</id>
      <content type="html">
        <![CDATA[
        <p>On Tuesday, <a href="http://twitter.com/johnfoliot">John Foliot</a> posted a little question on twitter.</p>
<blockquote>
<p>Question: why *CAN'T* we add ARIA directly to CSS? I haz use-cases | @<a href="https://twitter.com/glazou">glazou</a> @<a href="https://twitter.com/mollydotcom">mollydotcom</a> @<a href="https://twitter.com/fantasai">fantasai</a> @<a href="https://twitter.com/tabatkins">tabatkins</a></p>
<p>— John Foliot (@johnfoliot) <a href="https://twitter.com/johnfoliot/status/225275558328664064">July 17, 2012</a></p>
</blockquote>
<p>At first I thought this would be a bit crappy, adding accessibility to CSS which is for presentation sounded like a horrendous idea. Myself, <a href="http://twitter.com/johnfoliot">John</a>, <a href="http://twitter.com/mollydotcom">Molly</a> and <a href="http://twitter.com.inkpixelspaper">Jen</a> discussed this on the twitters a little further and I was still left not convinced. It seemed a horrible hack to try and get lazy assed developers to include aria roles to their sites. As I pointed out, if <a href="http://alwaystwisted.com/post.php?s=2012-06-01-your-website-stinks-on-mobile">developers are lazy enough</a> to not include all the <a href="http://alwaystwisted.com/post.php?s=2012-05-03-the-horse-has-bolted-oreally">relevant prefixes</a>, they'd probably not include this either (which is quite sad, really).</p>
<p>There was discussion that CSS is for presentation only, but i think with the onset of CSS3 animation whizz-bangs etc. we can adapt.</p>
<h2 id="roll-on-a-few-days." tabindex="-1">Roll on a few days.</h2>
<p>I'm currently sub-contracted by a client for some front-end development and consultancy on a site that's got a huge mega-nav, dropdown, suckerfish wotsit. It's huge, really huge and, of course, I wanted to make it accessible as possible. So I've added the relevant aria roles <a href="http://www.w3.org/TR/wai-aria/roles#menu">menu</a>, <a href="http://www.w3.org/TR/wai-aria/roles#menubar">menubar</a> and <a href="http://www.w3.org/TR/wai-aria/roles#menuitem">menuitem</a>. There were a lot of menu-items it got boring, very boring. I did use find and replace to help, luckily. So I was warming to John's idea around his question.</p>
<h2 id="how-can-it-be-done%3F" tabindex="-1">How can it be done?</h2>
<p>I tweeted that I was warming to it and struck up another quick conversation with John. He said that a colleague had suggested using attr as a CSS declaration. I think this makes perfect sense. So, for example, we've got a menu with 7 main menu links of which these have sub-menus containing 30 links. So that'd be 38 aria roles that need adding to your HTML.</p>
<h3 id="an-aside..." tabindex="-1">An aside...</h3>
<p>Adding all of that, those 38 aria roles to your HTML can make it look a little pale. Although correct, it'd even be cleaner if it was in the CSS. But I digress.</p>
<h2 id="in-the-css." tabindex="-1">In the CSS.</h2>
<p>So back to the CSS. To add the aria roles to the page now we could just write 3 lines of code within the CSS rather than 37 bits of code sprinkled around HTML.</p>
<p>nav { attr: menu; }
nav ul { attr: menubar; }
nav li { attr: menuitem; }</p>
<p>It's pretty easy isn't it? It's actually quite clean too. We could even use that for footer navigation too. This way our markup is lean, our CSS is snazzy and we're doing our best for accessibility, which is no bad thing.</p>
<h2 id="what-now%3F" tabindex="-1">What now?</h2>
<p>I don't really know, I guess someone (me?) needs to write this all up nicely and put it to the <a href="http://www.w3.org/blog/CSS/">CSS working group</a>. I haven't (currently) the time for this but hopefully I can make a start.</p>
<h2 id="what-about-you%3F" tabindex="-1">What about you?</h2>
<p>What do you think? Bad idea? Good idea? A problem that doesn't need solving?</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Stu goes Sass...</title>
      <link href="https://www.alwaystwisted.com/articles/stu-goes-sass.html"/>
      <updated>2012-07-08T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/stu-goes-sass.html</id>
      <content type="html">
        <![CDATA[
        <p>If you follow me on the twitters (and you should <a href="http://twitter.com/sturobson">follow me on the twitters</a>) you'll have know doubt seen that this last week or so I've been getting my head around Sass.</p>
<h2 id="disclaimer%3A" tabindex="-1">Disclaimer:</h2>
<p>I know I've written for my love for LESS on here <a href="http://alwaystwisted.com/post.php?s=2012-06-05-another-approach-to-mobile-first-css-whilst-supporting-internet-explorer">many</a>, <a href="http://alwaystwisted.com/post.php?s=2012-05-28-how-im-rolling-my-media-queries">many</a>, <a href="http://alwaystwisted.com/post.php?s=2012-05-17-content-choreography-mixins-in-less">many</a>, <a href="http://alwaystwisted.com/post.php?s=2012-05-05-everyday-im-bubbling-with-media-queries-and-less">many</a> <a href="http://alwaystwisted.com/post.php?s=2011-12-01-a-less-approach-to-mobile-first-css-supporting-older-ie-browsers">times</a>. I've still got the love for LESS but my current client requires Sass/SCSS so I've been learning that as quick as possible (note: if you know LESS it's not that difficult).</p>
<h2 id="loads-of-resources." tabindex="-1">Loads of resources.</h2>
<p>So basically this is a blogpost of all the resources I've been reading, re-reading and learning from to get my Sass/SCSS chops down. So here goes, in no order whatsoever.</p>
<p>A really good <a href="https://speakerdeck.com/u/imathis/p/sass-compass-the-future-of-stylesheets-now">Sass &amp; Compass slidedeck</a> from <a href="https://twitter.com/imathis">Brandon Mathis</a>.</p>
<p>A <a href="http://www.jc-designs.net/pdf/sassCheat.pdf">Sass/SCSS/Compass cheatsheet</a> pdf file to print off and stick on your MBA.</p>
<p>What's <a href="http://thesassway.com/intermediate/responsive-web-design-in-sass-using-media-queries-in-sass-32">coming in Sass 3.2</a> in regards to the coolness of media queries.</p>
<p><a href="http://susy.oddbird.net/">Susy</a>, a responsive grid system for/using Compass.</p>
<p>A front-end starter kit called <a href="https://github.com/tokokoo/pondasee">Pondasee</a>.</p>
<p>Another slidedeck - <a href="http://www.slideshare.net/BeritJensen/save-time-by-using-sassscss">save time by using Sass/SCSS</a>.</p>
<p>A blogpost on <a href="http://railslove.com/blog/2012/03/28/smacss-and-sass-the-future-of-stylesheets/">SMACSS and Sass</a>.</p>
<p><a href="http://compass-style.org/">Compass</a>, an open source framework for Sass.</p>
<p>A blogpost on calculating <a href="http://erskinelabs.com/calculating-ems-scss/">EMs with SCSS</a>.</p>
<p><a href="http://viget.com/inspire/sass-a-designers-perspective">Sass from a designers perspective</a> (blogpost).</p>
<p>A bunch of <a href="http://www.youtube.com/playlist?list=PL2CB1F80266E986EA&amp;feature=plcp">Sass tutorials on YouTube</a>.</p>
<p>I'm using the <a href="http://compass.handlino.com/">Compass.app</a> it's only 10 bucks!</p>
<p><a href="http://www.slideshare.net/adarowski/sassive-aggressive-level-up-your-css-with-sass">Sassive Agressive</a>, another slidedeck.</p>
<p><a href="http://sass-lang.com/">The Sass website</a>.</p>
<p><a href="https://github.com/thoughtbot/bourbon">Bourbon</a> (it's like Compass).</p>
<p><a href="http://css-tricks.com/sass-vs-less/">Sass vs. LESS</a> and <a href="http://css-tricks.com/video-screencasts/88-intro-to-compass-sass/">an intro to Sass/COMPASS</a> from <a href="http://twitter.com/chriscoyier">Chris Coyier</a>.</p>
<p>Part 1 of <a href="http://net.tutsplus.com/tutorials/other/mastering-sass-lesson-1/">Mastering Sass</a> from nettuts+.</p>
<p>The <a href="https://twitter.com/thesassway">@thesassway</a> twitter account.</p>
<p><a href="https://github.com/Snugug/Aura">Aura</a>, a responsive Sass and Compass framework from <a href="http://twitter.com/sungug">@sungug</a>.</p>
<p>Another framework, <a href="http://thecodingdesigner.com/">The coding designer</a></p>
<h2 id="finally." tabindex="-1">Finally.</h2>
<p>To top things off if, in the words of Bill Hicks, you're a reader there's a fantastic book to take you from the start - <a href="http://pragprog.com/book/pg_sass/pragmatic-guide-to-sass">The Pragmatic Guide To Sass</a> - available in all good retailers I'm sure.</p>
<h2 id="one-more-thing." tabindex="-1">One More Thing.</h2>
<p>I'm sure I've missed your post, video, twitter account. If you've got some fantastic Sass/SCSS/Compass resource I've missed out on then please do add a comment to this post. Let's get a big resource going.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Rejuvenate your inbox with some web development newsletters</title>
      <link href="https://www.alwaystwisted.com/articles/rejuvenate-your-inbox-with-some-web-development-newsletters.html"/>
      <updated>2012-06-23T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/rejuvenate-your-inbox-with-some-web-development-newsletters.html</id>
      <content type="html">
        <![CDATA[
        <p>Daily we can get access to new and fantastic news, techniques, processes for our jobs. Sometimes we miss things. Sometimes we're too busy doing the actual 'work' part of our jobs to keep up with current 'trends' and these new new things.</p>
<p>So why not sign up to some email newsletters? Get yourselves a lovely weekly digest straight in your inbox. Read it at your desk, on the commute, even in the loo. Letting someone else collate the news and give you a nice 'précis' is a perfect way to keep your head above water.</p>
<p>Here are a few I sign up to.</p>
<p><a href="http://web-design-weekly.com/">Web Design Weekly</a></p>
<p>Giving you some news, techniques, tutorials and inspirational pieces weekly.</p>
<p><a href="http://css-weekly.com/">CSS Weekly</a></p>
<p>Some select articels all about what's being created and said about CSS and CSS3.</p>
<p><a href="http://html5weekly.com/">HTML5 Weekly</a></p>
<p>All things HTML5, not just the markup. News, articles, tools, videos, demos and more.</p>
<p><a href="http://www.webdeveloperweekly.com/">Web Developer Weekly</a></p>
<p>An email of 'all things' web developer.</p>
<p><a href="http://responsivedesignweekly.com/">Responsive Design Weekly</a></p>
<p>Some fantastically collated news, tutorials, presentations, tools and resources all about responsive web design.</p>
<p><a href="http://bradfrostweb.com/responsive-web-design-newsletter/">Responsive Web Design Newsletter</a></p>
<p>Another equally fantastic collation of information for all things responsive from that handsome chap <a href="http://twitter.com/brad_frost">Brad Frost</a>.</p>
<h3 id="updates" tabindex="-1">Updates</h3>
<p>Just after throwing this post up on the twitters that fancyman of Croydon <a href="http://twitter.com/mrqwest">MrQwest</a> suggested adding <a href="http://javascriptweekly.com/">Javascript Weekly</a> to the list. Whilst lookin at it and signing up I then found out about <a href="http://rubyweekly.com/">Ruby Weeky</a> too.</p>
<p>So are there any more out there? Please add them to the comments.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>We&#39;re all reading the same book, but we&#39;re all on different pages.</title>
      <link href="https://www.alwaystwisted.com/articles/were-all-reading-the-same-book-but-were-all-on-different-pages.html"/>
      <updated>2012-06-20T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/were-all-reading-the-same-book-but-were-all-on-different-pages.html</id>
      <content type="html">
        <![CDATA[
        <p>There has been quite a few blogposts from different online magazines recently that has been given a bit of a backlash on the twitters. Some of these posts have been considered incorrect, factually biased or just 'plain wrong'. Some have been questioned as to why such a 'well known' topic needs rewriting today where they one from a couple of years ago works just fine.</p>
<h2 id="it's-pretty-simple..." tabindex="-1">It's pretty simple...</h2>
<p>Think of the web industry and your career as a book. We're all reading the same book but some of us are faster readers than others. Some of us misread chapter three and four. Some of us have skipped a couple of chapters to get to the juicy bits. Some of us are only starting on chapter one, page one today.</p>
<p>If we think of this industry along with our careers like this, it's easier to understand why such a post has been written. Whether completely incorrect or just a repeat of what you already know.</p>
<h2 id="be-excellent-to-each-other..." tabindex="-1">Be excellent to each other...</h2>
<p>If the post you read is completely incorrect, factually wrong and full of horse shit. Don't slate the writer because let's face it they're probably a few chapters behind you. Be <a href="https://www.youtube.com/watch?v=3bTvDKcxZuY">excellent to each other</a>. Offer your criticisms a polite way (a direct email, a comment on the post). Be civil. Calling stuff out to your twitter followers as horse shit (or similar) does yourself, them and the world no favours. Stop that.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Another approach to mobile first CSS whilst supporting Internet Explorer</title>
      <link href="https://www.alwaystwisted.com/articles/another-approach-to-mobile-first-css-whilst-supporting-internet-explorer.html"/>
      <updated>2012-06-05T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/another-approach-to-mobile-first-css-whilst-supporting-internet-explorer.html</id>
      <content type="html">
        <![CDATA[
        <p>Back in December I wrote a blogpost on <a href="http://alwaystwisted.com/post.php?s=2011-12-01-a-less-approach-to-mobile-first-css-supporting-older-ie-browsers">a LESS approach for mobile first CSS &amp; supporting older IE browsers</a> where I described the current ways (at the time) of creating a IE specific stylesheet from several seperate files. I also described how I thought it should work and since the launch of LESS.js version 1.2.0 it's easier than ever to do.</p>
<p>Roll on 6 months and I have changed how <a href="http://alwaystwisted.com/post.php?s=2012-05-28-how-im-rolling-my-media-queries">I intend to write my LESS</a> using <a href="http://alwaystwisted.com/post.php?s=2012-05-05-everyday-im-bubbling-with-media-queries-and-less">media query bubbling</a> that keep the media queries within the element which I find easier when editing. Which looks like this.</p>
<p>header {
background-color: red;
@media screen only and (min-width: 20em) {
background-color: blue;
}
}</p>
<p>An overhead I've still yet to test is performance but I still hazard a guess that it'd be negligible.</p>
<h2 id="a-back-story." tabindex="-1">A back story.</h2>
<p>Last Wednesday (May 30th 2012) <a href="http://twitter.com/boagworld">Paul Boag</a> wrote a post <a href="http://boagworld.com/tumblog/putting-media-queries-in-their-place/">exclaiming his wishes</a> for LESS which media query pretty much caters for. After a quick firing of tweets Paul also wanted to support those browsers (IE 7 &amp; 8) that don't support CSS3 media queries.</p>
<p>I mentioned that he could use the original technique I blogged about, but this wouldn't allow him to use bubbling. I also mentioned he could 'do a cron job' to strip out the media query rules that <a href="http://twitter.com/richquick">Rich Quick</a> mentioned at the <a href="http://port80events.co.uk/">Port 80</a> conference earlier in May (<a href="http://www.slideshare.net/richardfquick/rwd-in-the-wild">slides</a>).</p>
<h2 id="a-workable-solution." tabindex="-1">A Workable Solution.</h2>
<p>After much head scratching I found a way to create some internet explorer specific styles within your LESS files whilst still using media query bubbling.</p>
<p>First off we need to 'borrow' the <a href="http://paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/">HTML conditional classes</a> that are used within the <a href="http://html5boilerplate.com/">HTML5 boilerplate</a>. I say borrow as personally I don't take the code verbatim and have stripped out bits, changed little things so it works more for me as I code differently to you as you do to me.</p>
<p>This is the HTML code we need</p>
<!--\[if lt IE 7\]> <html class='no-js lt-ie9 lt-ie8 lt-ie7' lang='en'> <!\[endif\]-->
<!--\[if IE 7\]>    <html class='no-js lt-ie9 lt-ie8' lang='en'> <!\[endif\]-->
<!--\[if IE 8\]>    <html class='no-js lt-ie9' lang='en'> <!\[endif\]-->
<!--\[if gt IE 8\]><!--> <html class='no-js' lang='en'> <!--<!\[endif\]-->
<p>Now we've got that at the top of our HTML page straight after the doctype declaration we're good to go with diving into our LESS file.</p>
<p>As I mentioned above I've started writing my LESS like this.</p>
<p>header {
background-color: red;
@media screen only and (min-width: 20em) {
background-color: blue;
}
}</p>
<p>Which when compiled into CSS returns us with this.</p>
<p>header {
background-color: red;
}</p>
<p>@media screen only and (min-width: 20em) {
header {
background-color: blue;
}
}</p>
<p>Here we have our mobile first or 'base' CSS style to the element (in this case the background colour of the header will be red for devices and browsers that don't support media queries). What we could now do is add some code to the LESS file that'll give the <header> a IE specific class. This is achieved by writing something like this</p>
<p>~.lt-ie8&amp;&amp;&amp; { background-color: green; }~</p>
<p>.lt-ie8&amp; { background-color: green; }</p>
<p>This uses ~&amp;&amp;&amp;~ &amp; which takes the preceding element and then puts the .lt-ie8 class in front of it. So for example writing this LESS.</p>
<p>header {
background-color: red;</p>
<p>~.lt-ie8&amp;&amp;&amp; {
background-color: blue;
}~</p>
<p>.lt-ie8&amp; {
background-color: blue;
}</p>
<p>}</p>
<p>Gives us this CSS.</p>
<p>header {
background-color: red;
}
.lt-ie8 header{
background-color: blue;
}</p>
<p>As you can see we're half way there to media query bubbling anyway so by doing this.</p>
<p>header {
background-color: red;</p>
<p>~.lt-ie8&amp;&amp;&amp; {
background-color: blue;
}~
.lt-ie8&amp;&amp;&amp; {</p>
<p>background-color: blue;
}</p>
<p>@media screen only and (min-width: 20em) { background-color: green; } }</p>
<p>We would then, when compiled, get this CSS.</p>
<p>header {
background-color: red;
}</p>
<p>.lt-ie8 header {
background-color: blue;
}</p>
<p>@media screen only and (min-width: 20em) {
header {
background-color: green;
}
}</p>
<p>This way we can then have our mobile first (or base) style, followed by class specific styles for whichever browsers you are supporting on your project and then all the fun of the fair in the media queries.</p>
<h2 id="caveat." tabindex="-1">Caveat.</h2>
<p>Of course this does mean you could be duplicating some of the outputted CSS but a bonus means you could also be more specific.</p>
<h2 id="but..." tabindex="-1">But...</h2>
<p>Perhaps you only want to give IE6-7 a static, fixed width 'base' design and give IE8 a hybrid fixed/responsive site. With this way of writing your code, you now can do. Easy to create and using this technique easliy maintainable.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Your website stinks on mobile...</title>
      <link href="https://www.alwaystwisted.com/articles/your-website-stinks-on-mobile.html"/>
      <updated>2012-06-01T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/your-website-stinks-on-mobile.html</id>
      <content type="html">
        <![CDATA[
        <p>You should stop being such a lazy-assed developer.</p>
<p>There's just too many devices out there to just test on your resizable desktop browser for any excuse not to test on at least the device(s) you own.</p>
<p>Almost everyday I visit a new site or a redesign that effectively breaks in some fashion on my iPhone (other phones are available and yes I have some of those too).</p>
<p>You see, no matter how it looks on your desktop browser. When viewing it on a mobile device it can break. It could be a really long url in a blog post comment, it could be the <code> in your latest blogpost or it could be that new demo video that's breaking out of the devices viewport. All of which, I feel, makes your lovely collection of pixels tarred with a smack of laziness.</p>
<p>You should be testing on the device(s) you're developing your site for. It's 2012, you've got to step up your game. <a href="http://www.lukew.com/ff/entry.asp?1506">Mobile is getting big</a> so test on what you have or can beg, borrow but not steal. If you don't you're being incredulouos to your craft and this profession.</p>
<h2 id="a-back-story." tabindex="-1">A back story.</h2>
<p>When I saw these issues on my iPhone, I used to tweet the sites creator and try and explain what's broken as succinctly as a I could. Sometimes this was greatly appreciated, mostly it 'fell on deaf ears'. So after months of slowly getting 'less interested' in trying to help I've generally stopped. It's not my problem that you've been lazy in the development of the site not to test it on (at least one of) the devices you're expecting it to work on.</p>
<p>Take your head out of your ass and test your site on all the things.</p>
<h2 id="what-can-be-done." tabindex="-1">What can be done.</h2>
<p>Well, luckily there's many things you can do to start and, I repeat, you should. I'm sure you've got an internet enabled device. You might even be reading this post on your iPhone or 'droid. So why aren't you testing every aspect of your site on it, thinking of every eventaullity that could break it?</p>
<p>You may only have one phone, but you should really consider getting more. There are a <a href="http://bradfrostweb.com/blog/mobile/test-on-real-mobile-devices-without-breaking-the-bank/">couple</a> of <a href="http://stephanierieger.com/strategies-for-choosing-test-devices/">posts</a> on which devices you should consider choosing and I've got a little tumblog on other <a href="http://mytestsuite.tumblr.com/">peoples test suites</a> so you can get an idea of what other developers are using.</p>
<h2 id="buy-devices." tabindex="-1">Buy Devices.</h2>
<p>You need more than one device. I'd at least recommend getting an iOS device and a 'droid. You don't need an iPhone and you don't need it all to be new. A 2nd hand iPod Touch would work just as well. For your Android device, there's plenty to choose, plenty of ever differing operating systems also. Going with some recent <a href="http://developer.android.com/resources/dashboard/platform-versions.html">platform version statistics</a> I'd go with Android 2.3.3. A quick note is to not purchase a 'droid that uses GetJar as it's app marketplace. Invariably you can't download any other browsers.</p>
<h2 id="install-those-browsers." tabindex="-1">Install those browsers.</h2>
<p>For iOS you'll get mobile Safari but also <a href="http://www.google.co.uk/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=1&amp;ved=0CIMBEBYwAA&amp;url=http%3A%2F%2Fitunes.apple.com%2Fgb%2Fapp%2Fopera-mini-web-browser%2Fid363729560%3Fmt%3D8&amp;ei=DsjJT7G2H8KW8QO6kPEC&amp;usg=AFQjCNFO5IO_FaVkTJ4R-gkxSkeZYImKOQ&amp;sig2=25AJ9JQ6H4KC2RHLZQKfIQ">download</a> Opera mini. For Android you've a plethora of choice. It comes with it's own 'Browser' but you should install Opera mini, Opera Mobile, Dolphin HD and Dolphin mini. If you have or purhcase a <a href="http://www.mozilla.org/en-US/mobile/platforms/">'qualifying' device</a> you could and should also install Firefox for mobile.</p>
<h2 id="hiding-in-the-shadows." tabindex="-1">Hiding in the shadows.</h2>
<p>Recently launched <a href="http://labs.adobe.com/technologies/shadow/">Adobe Shadow</a> allows you to test, inspect and preview your desgins on your iOs or Android device. It allows you to edit on your laptop/desktop and see what's being rendered on your device. Which in turn will make your development that little bit quicker and will help iron out the creases of your design you've previoulsy just tested on a resizable browser.</p>
<h2 id="emulates." tabindex="-1">Emulates.</h2>
<p>Another recently launched product is Opera Softwares <a href="http://www.opera.com/developer/tools/mobile/">Opera Mini Emulator</a> which allows you to view how your site could look on several devices. You can pair this up with Opera's <a href="http://www.opera.com/developer/tools/">Dragonfly</a> to edit the code too (a <a href="http://www.youtube.com/watch?v=YHwiaH8Z5vA">video demo of Dragonfly</a> from Patrick).</p>
<p>If you haven't got an iOS device and can't afford to purchase a iPod Touch you could try the emulator that comes with Xcode as well. Here's a nice little how too on <a href="http://kevinthompson.info/blog/iphone-and-ipad-browser-testing-using-the-ios-simulator/">getting it set up</a>.</p>
<h2 id="blackberries." tabindex="-1">Blackberries.</h2>
<p>Well they're getting cheaper to buy 2nd hand or you could use the <a href="http://us.blackberry.com/developers/resources/simulators.jsp">emulator</a> but you should really think about them in your designs. For example, there v5.0 browser (found on the populat <a href="http://uk.blackberry.com/devices/blackberrycurve8520/features.jsp">8520</a>) doesn't suppoer CSS3 media queries very well. So your responsive design could look pretty crappy.</p>
<h2 id="you-have-to-touch-it." tabindex="-1">You have to touch it.</h2>
<p>As well as what your site 'looks like' on a mobile device, without testing on them you won't know how 'they feel'. Your finger or thumb is not a mouse cursor. Your sites visitors precision will be off. Your site might be easily accessible by touch but it could be a pain in the frickin' ass when using a thumbwheel.</p>
<h2 id="if-you-must." tabindex="-1">If you must.</h2>
<p>If you find yourself only resorting to using Chrome or even just for quick things then <a href="http://twitter.com/paulmist">Paul Mist</a> showed me this little <a href="https://gist.github.com/2857377">bit of JavaScript</a> that you can save as a bookmark to create a 'iPhone sized' browser window to test in.</p>
<h2 id="do-as-much-as-you-can-and-at-least-do-something." tabindex="-1">Do as much as you can and at least do something.</h2>
<p>Going back to basics. Just please, test your sites design on whatever you have to hand and not just on your browser of choice.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>How I&#39;m rolling my media queries</title>
      <link href="https://www.alwaystwisted.com/articles/how-im-rolling-my-media-queries.html"/>
      <updated>2012-05-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/how-im-rolling-my-media-queries.html</id>
      <content type="html">
        <![CDATA[
        <p>As I've previously mentioned, I start with a default set of <a href="http://alwaystwisted.com/post.php?s=2012-04-28-a-common-set-of-breakpoints-to-start">common breakpoints</a> when I'm creating my responsive stylesheets. Recently you may also have seen a post where I discuss the exciting <a href="http://alwaystwisted.com/post.php?s=2012-05-05-everyday-im-bubbling-with-media-queries-and-less">Media Query bubbling</a> that's available in LESS. So I thought I'd write a quick post on how I'm currently rolling out media queries in my stylesheets.</p>
<h2 id="snippets" tabindex="-1">Snippets</h2>
<p>First off, I used Espresso for my code editor. I know there's many a code editor available and having spent almost 12 years in dreamweaver prior to purchasing, this app suits my 'workflow'.</p>
<p>So, to start I've created several <a href="http://wiki.macrabbit.com/index/Snippets/">snippets</a> in the app for my common breakpoints which are 320, 480, 600, 768, 900, 1100 &amp; 1300px (although these are stipulated in ems based on 1em = 16px).</p>
<p>This means that if I type 320 then hit 'tab' the following code gets put in place</p>
<p>@media screen and (min-width:  20em) {</p>
<p>I can then write the rules that I'd like within this query and close it at the end. I have also created a 'blank' media query snippet for 'ordinary' media queries and device media queries. Which are mq + 'tab' and dmq + 'tab' that will give you this code</p>
<p>@media only screen and (min-width :  ) {
}</p>
<p>@media only screen and (min-device-width :  ) {
}</p>
<h2 id="bubbles%3F" tabindex="-1">Bubbles?</h2>
<p>Like I said at the start, I'm now implementing the use of media query 'bubbling' in my LESS files. For me that keeps all the elements and there selectors close together. Not in seperate 'media query files. All together, under one roof and with the media query within it so I can see at ease what I'm playing with and if I've already added 10px of padding to that element already, straight away. Without having to find it and check.</p>
<h2 id="sorted!" tabindex="-1">Sorted!</h2>
<p>So I can quickly create my CSS using LESS. I can start with my base styles. Quickly add a media query (common or not) with snippets so that I can alter what's needed when it starts to look <a href="https://twitter.com/brad_frost/statuses/191977076000161793">shit</a>. I can see at a glance what element has what CSS effecting it and where and it's simple (with snippets) to add as many media queries as I so wish. So I could end up with a LESS file like this snippet.</p>
<p>header {
body: background-color: blue;
 @media screen and (min-width:  20em) {
body: background-color: red;
}</p>
<p>@media screen and (min-width:  37.5em) {
body: background-color: green;
}</p>
<p>@media screen and (min-width:  48em) {
body: background-color: blue;
}</p>
<p>@media screen and (min-width:  1176px) {
body: background-color: orange;
}
}</p>
<h2 id="ta-da!" tabindex="-1">Ta-da!</h2>
<p>Not the greatest blogpost I know, but I'd just thought I'd share a little insight into how I'm 'doing it' with responsive web design, LESS and media query bubblin'</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Content Choreography Mixins In LESS</title>
      <link href="https://www.alwaystwisted.com/articles/content-choreography-mixins-in-less.html"/>
      <updated>2012-05-17T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/content-choreography-mixins-in-less.html</id>
      <content type="html">
        <![CDATA[
        <p>With the new fangled-ness of CSS3 we've been given a treat in box-orient and box-ordinal group, at some point last year I started creating a <a href="http://alwaystwisted.com/backstage/css3-box.html">little demo</a> for a nice reponsive idea for mobile first navigation but stopped (for some reason that escapes me).</p>
<h2 id="recently." tabindex="-1">Recently.</h2>
<p>Just recently that <a href="https://twitter.com/jordanmoore">Jordan Moore</a> created a <a href="http://www.jordanm.co.uk/post/21863299677/building-with-content-choreography">lovely little post</a> on content choreography that takes these two CSS3 selectors and (with a mobile first, responsive approach) <a href="http://www.jordanm.co.uk/contentchoreography">demontstrates</a> <a href="http://www.jordanm.co.uk/contentchoreographydemo">how</a> to move your content for various devices.</p>
<h2 id="just-today." tabindex="-1">Just Today.</h2>
<p>Today whilst perusing the twitters, I saw this tweet from Jordan -</p>
<blockquote>
<p>Content Choreography made even easier with @<a href="https://twitter.com/irishstu">irishstu</a>'s lovely little SASS mixin - <a href="http://t.co/x1YdREa8" title="http://blog.woop.ie/post/23227066135/content-choreography-mixin">blog.woop.ie/post/232270661…</a> <a href="https://twitter.com/search/%2523rwd">#rwd</a></p>
<p>— Jordan Moore (@jordanmoore) <a href="https://twitter.com/jordanmoore/status/203114164120596481">May 17, 2012</a></p>
</blockquote>
<p>I soon tweeted back saying that I'll knock this up in LESS later, and here is that post.</p>
<h2 id="to-start-with." tabindex="-1">To start with.</h2>
<p>The first LESS mixin we will create is for the container (probably <body>) so that it'll initiate the relevant box-orient -</p>
<p>.boxit(@box-dir) {
display:-webkit-box;
display:   -moz-box;
display:        box;</p>
<p>-webkit-box-orient:@box-dir;
-moz-box-orient:@box-dir;
-ms-box-orient:@box-dir;
box-orient:@box-dir;
}</p>
<p>So for the @box-dir in this mixin you can choose horizontal, vertical, inline-axis, block-axis or inherit&gt; For more information check out the <a href="https://developer.mozilla.org/en/CSS/box-orient">MDN post here</a>.</p>
<p>For example, your LESS file would contain this  -</p>
<p>body { .boxit(vertical); }</p>
<p>Which would give the resulting CSS -</p>
<p>body {
display:-webkit-box;
display:   -moz-box;
display:        box;</p>
<p>-webkit-box-orient:vertical;
-moz-box-orient:vertical;
-ms-box-orient:vertical;
box-orient:vertical;
}</p>
<h2 id="now%2C-order-it." tabindex="-1">Now, order it.</h2>
<p>The second mixin allows you to specifiy where you wish the content to be. The LESS code for this is -</p>
<p>.box-order(@box-order-number: 1) {
-webkit-box-ordinal-group: @box-order-number;
-moz-box-ordinal-group: @box-order-number;
-ms-box-ordinal-group: @box-order-number;
box-ordinal-group: @box-order-number;
}</p>
<p>This allows you to easily define the number order in the chosen box-orient. So you'd write your LESS like this -</p>
<p>h1 { .box-order(3); }
h2 { .box-order; }</p>
<p>Which would give this result -</p>
<p>h1 {
-webkit-box-ordinal-group: 3;
-moz-box-ordinal-group: 3;
-ms-box-ordinal-group: 3
box-ordinal-group: 3;
}</p>
<p>h2 {
-webkit-box-ordinal-group: 1;
-moz-box-ordinal-group: 1;
-ms-box-ordinal-group: 1;
box-ordinal-group: 1;
}</p>
<h2 id="and-there-we-have-it." tabindex="-1">And there we have it.</h2>
<p>Here's the LESS version of the <a href="http://blog.woop.ie/post/23227066135/content-choreography-mixin">Sass</a> version from eariler today</p>
<h2 id="an-update-(12%2F06%2F12)" tabindex="-1">An Update (12/06/12)</h2>
<p>After creating this post I thought that, really, I should include the swift becoming new CSS3 <a href="https://developer.mozilla.org/en/Using_flexbox">flexbox</a> code, as what's written above, although 'current' in some browsers, will soon be depreciated.</p>
<p>So to use the new hawtness of <a href="http://dev.w3.org/csswg/css3-flexbox/">CSS3 Flexbox</a> we first, again, need to (using LESS) set it up in the body.</p>
<p>.flexit(@flex-dir) {</p>
<p>display:-webkit-flex;
display:-moz-flex;
display:-ms-flex;
display:-o-flex;
display: flex;</p>
<p>-webkit-flex-direction:@flex-dir;
-moz-flex-direction:@flex-dir;
-ms-flex-direction:@flex-dir;
-o-flex-direction:@flex-dir;
flex-direction:@flex-dir;</p>
<p>}</p>
<p>As you can see that where we had display: box; the new spec is display: flex;</p>
<p>I've included a new mixin as <a href="https://developer.mozilla.org/en/CSS/flex-direction">flex-direction</a> has different properties than <a href="https://developer.mozilla.org/en/CSS/box-orient">box-orient</a>.</p>
<p>Also instead of box-ordinal-group, the new spec uses a simple single word, order. Because the value is still numeric we can fit both spec's (if you wanted to) into the same mixin.</p>
<p>.box-order(@box-order-number: 1) {</p>
<p>-webkit-box-ordinal-group: @box-order-number;
-moz-box-ordinal-group: @box-order-number;
box-ordinal-group: @box-order-number;</p>
<p>-webkit-box-order: @box-order-number;
-moz-order: @box-order-number;
-ms-order: @box-order-number;
-o-order: @box-order-number;
order: @box-order-number;</p>
<p>}</p>
<p>Using these two new mixins you're now set for world dominence, except Opera, they're not supporting it, yet (but I've included for prefix for when they do).</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Screwing the srcset</title>
      <link href="https://www.alwaystwisted.com/articles/screwing-the-srcset.html"/>
      <updated>2012-05-16T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/screwing-the-srcset.html</id>
      <content type="html">
        <![CDATA[
        <p>As much as I wasn't convinced with how the addition of srcset was included in the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#attr-img-srcset">spec</a>, what a difference a day makes.</p>
<p>At first I was not a fan of it's appaling syntax, but after a quick email from <a href="http://twitter.com/adactio">Jeremy</a> in the <a href="http://lists.w3.org/Archives/Public/public-whatwg-archive/2012May/0320.html">WhatWG email list</a> I was a little more convinced.</p>
<h2 id="in-fact." tabindex="-1">In Fact.</h2>
<p>Before we go any further you should really read <a href="http://adactio.com">Jeremy's</a> fantastic <a href="http://adactio.com/journal/5474/">post</a> of calmness and tranquility in explaining what has happened up until this point.</p>
<p>Back yet? You migh want to read Dr. <a href="http://twitter.com/brucel">Bruce's</a> <a href="http://html5doctor.com/html5-adaptive-images-end-of-round-one/">post</a> to.</p>
<p>You there? Cool. Now my issue is with the current <a href="http://odin.s0.no/web/srcset/polyfill.htm">polyfill</a> that 'showed itsself' in my timeline on the twitter this morning.</p>
<h2 id="a-srcset-polyfill" tabindex="-1">A srcset polyfill</h2>
<p>Ok, There's quite a bit of the polyfill I don't like so let's make a start ok? Ready? Let's go.</p>
<p>Let's have a look at the polyfill's HTML</p>
<p><img alt='' srcset='big.png 1100w, medium.png 500w, small.png 200w' style='display:none' /> <noscript>
<img src='small.png' alt='Noscript alt'></noscript></p>
<h3 id="no" tabindex="-1">no <img src=''></h3>
<p>In the polyfill there is not an initial image file like there is in the spec. I don't think that's good at all, it's not very '<a href="http://futurefriend.ly/">future friendly</a>'. So to fix that, let's add it to the HTML. While we're at it, let's tidy it up a little too.</p>
<p><img src='small.png'
      srcset='big.png 1100w,
              medium.png 500w,
              small.png 200w'
          alt='alt text'
        style='display:none'
    />
<noscript><img src='small.png' alt='Noscript alt'></noscript></p>
<p>That's better, but that's not it is it?</p>
<h3 id="display%3A-none%3B-is-utter-filth" tabindex="-1">Display: none; is utter filth</h3>
<p>As you can see in the HTML above the polyfill has put display: inline; inline with the HTML rather than within the CSS. Let's fix that.</p>
<p>So first up let's remove it from the HTML</p>
<p><img src='small.png'
      srcset='big.png 1100w,
              medium.png 500w,
              small.png 200w'
          alt='alt text'
    />
<noscript><img src='small.png' alt='Noscript alt'></noscript></p>
<p>Now we've done that, let's add it to the CSS</p>
<p>img { display: none; }</p>
<p>Nice, sorted right?</p>
<h3 id="switching-around-the-javascript" tabindex="-1">Switching around the JavaScript</h3>
<p>At the bottom of the JS file, where the original polyfill is hacking around the <img> tag it does this -</p>
<p>// Remove the stupid display:none made to hide the alt-text
img.style.display = ''</p>
<p>As we've now put display:none; in the CSS we need to change that by simply added 'block' where '' is (let's change the comment too) -</p>
<p>// Change the style of the <img /> element to display decided upon image
img.style.display = 'block'â€‹</p>
<p>This now means that the polyfill will display the <img>. Good? Well, just one more thing.</p>
<h3 id="no%2C-no%2C-no%2C-no%2C" tabindex="-1">No, no, no, no, <noscript></h3>
<p>At the end of the polyfill HTML code is the <noscript> tag with the small images so there's a fallback for browsers that don't have JavaScript enabled. Because we've added display: none; to the <img> elements in CSS, the <noscript> <img>'s will be 'hidden' too. So we need to change that in the CSS, like this -</p>
<p>noscript img { display: inline; }</p>
<p>Excellent, that's great, isn't it? We fixed the internet right?</p>
<h2 id="ta-da!" tabindex="-1">Ta-Da!</h2>
<p>So. Here's <a href="http://jsfiddle.net/sturobson/2t3xt/16/">all the code</a> for the polyfill that I've edited to this state.</p>
<h3 id="but%2C-two-images%3F" tabindex="-1">But, Two images?</h3>
<p>Unfortunately because <a href="http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/">how browsers work</a> this polyfill has the bastard audacity to download two images when all we need is one. This is because of our using of display:none; and calling an image at first then, with Javascript, calling the 'appropriate' image. That's an extra http request that could be costly and also some more page weight that could be detrimental. For the short term, that's something that could be ok though right?</p>
<h2 id="well%2C-not-really..." tabindex="-1">Well, not really...</h2>
<p>That's about as far as my 'knowledge and understanding' can probably take it. I'm sure it can be improved upon, refactored, edited, fucked with and corrected. I do feel it's a little bit 'cleaner and meaner' than the original polyfill I've edited.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Create a responsive mobile first menu</title>
      <link href="https://www.alwaystwisted.com/articles/create-a-responsive-mobile-first-menu.html"/>
      <updated>2012-05-14T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/create-a-responsive-mobile-first-menu.html</id>
      <content type="html">
        <![CDATA[
        <h1 id="part-2-of-a-series-looking-at-progressively-enhanced%2C-mobile-first%2C-reponsive-navigation" tabindex="-1">Part 2 of a series looking at progressively enhanced, mobile first, reponsive navigation</h1>
<p>In the <a href="http://alwaystwisted.com/post.php?s=2012-05-12-create-a-pure-css-menu-button">first part of this mini series</a> we looked at creating a menu icon for what I believe to be the <a href="http://stuffandnonsense.co.uk/blog/about/we_need_a_standard_show_navigation_icon_for_responsive_web_design">best solution</a> for your site's <a href="http://bradfrostweb.com/blog/web/responsive-nav-patterns/">mobile navigation</a>.</p>
<p>The outcome was to create an icon by creating an HTML element similar to this -</p>
<p>HTML</p>
<div id='nav-btn'></div>
<p>Which would then be styled with CSS like this -</p>
<p>CSS</p>
<p>#nav-btn {</p>
<p>background: transparent; 
border-bottom: 23px double #121212; 
border-top: 8px solid #121212;
height: 7px; 
width:37px;
}</p>
<p>Result</p>
<h2 id="making-an-example." tabindex="-1">Making an example.</h2>
<p>Ok, so let's start making a quick example page with some links that we're going to want to manipulate with this button. I could bore you with the HTML and CSS of this but I'm sure you know how to do that kinda stuff, and if not. You can see it from the resulting JSFiddle below -</p>
<h2 id="querying-your-users-viewport." tabindex="-1">Querying your users viewport.</h2>
<p>Now for this example, I only want the resulting show/hide menu icon to work on small viewports. Not only do I want to only have this working for small viewports (less than 767px for arguements sake) I was also only want it to work on devices such as an iPhone or Android mobile phone. Therefore whereas we would normally use this kind of media query -</p>
<p>@media only screen and (min-width: 240px) {
/* CSS Rules to go here */
}</p>
<p>We are instead going to define a media query as follows that should only affect viewports found on popular mobile phones, like this -</p>
<p>@media only screen and (min-device-width: 1px) and (max-device-width: 767px) {
/* CSS Rules to go here */
}</p>
<p>The min-device-width and max-device-width media query rules struggle to work in Android 2.2 so to combat this make sure you've got something similar to this in your HTML</p>
<p><meta content='width=device-width,initial-scale=1' name='viewport' /></p>
<p>So with this media query we're going to hide the nav element and restyle it.</p>
<p>An updated example (note: this will only look different on your mobile device) -</p>
<h2 id="but-first%2C-where's-that-menu-button-gone%3F" tabindex="-1">But first, where's that menu button gone?</h2>
<p>In the HTML of the last code example I have not included the DIV for the button. This is because it is going to be added with JavaScript and jQuery. This makes our original HTML cleaner and means your site will be more <a href="http://www.alistapart.com/articles/understandingprogressiveenhancement/">progressively enhanced</a> and will <a href="http://dev.opera.com/articles/view/graceful-degradation-progressive-enhancement/#gracefulprogressivenutshell">degrade gracefully</a> when the user has JavaSCript disabled or they're a blackberry user *winks*.</p>
<h2 id="getting-the-javascript-going." tabindex="-1">Getting the Javascript going.</h2>
<p>So, we're going to add the navigation (menu) button with some JavaScript/jQuery. To do this we're going to use jQuery's prepend, like this -</p>
<p>$('#container').prepend('<div id='nav-btn'></div>');</p>
<p>Well that's all well and good, but.</p>
<h2 id="c'mon%2C-c'mon%2C-c'mon%2C-touch-me." tabindex="-1">C'mon, c'mon, c'mon, Touch me.</h2>
<p>The menu icon is perfect for touch, not so much for a device that'll recognise the media queries but doesn't have touch. So we're going to throw that bit of jQuery into an if statement in JavaScript to only appear if the device has touch. Like this -</p>
<p>if ('ontouchstart' in document.documentElement)</p>
<p>// It's a touch screen device.</p>
<p>// create the button div
$('#container').prepend('<div id='nav-btn'></div>');
}</p>
<p>else 
{
}</p>
<p>So to tie-in with our device-width media queries this should now show the menu button when viewed on a touch screen device which's viewport is no bigger than 767px.</p>
<h2 id="more-styling%3F-more-javascript%2Fjquery%3F" tabindex="-1">More Styling? More JavaScript/jQuery?</h2>
<p>I want to style the navigation links differently if the device is touch enabled. As much as I have previously said how I dislike a <a href="http://alwaystwisted.com/post.php?s=2011-02-20-dont-let-your-menu-take-over">screen full of links</a> having a menu button that shows and hides the navigation is screaming out for nice big links for our chuby fingers to tap, But to progressively enhance this bad boy we only want it changed on devices that have JavaScript enabled. Therefore we're going to add a class the contents #container. Whilst we're at it let's add the show/hide jQuery code too. Like this -</p>
<p>if ('ontouchstart' in document.documentElement)
{
// It's a touch screen device.</p>
<p>// add claas of touch to container for the CSS 
$('#container').addClass('touch');</p>
<p>// create the button div
$('#container').prepend('<div id='nav-btn'></div>');</p>
<p>// make the button div a toggle show/hide$('#nav-btn').click(function(){
$('nav').toggle();
return false;
})
}</p>
<p>else 
{
}</p>
<p>Now we add the .touch to the relevant CSS. Here's the updated example.</p>
<p>Having a quick play with this I noticed the dreaded <a href="http://paulirish.com/2009/avoiding-the-fouc-v3/">FOUC</a>. So, first I added a 'noJs' class to my HTML then included the following code to swap it with just 'JS' if JavaScript is enabled</p>
<p><script>
(function(H){H.className=H.className.replace(/bnojsb/,'js')})
(document.documentElement)
</script></p>
<p>After this I changed the display: none; attirbute for the <nav> element to work if the document has a JS class which gets rid of the FOUC and degrades nicely as well.</p>
<h2 id="you've-hidden-it%3F-but%3F" tabindex="-1">You've hidden it? But?</h2>
<p>Of course, hiding the <nav> element with display: none; when JavaScript is enabled will hide it regardless of whether the device viewing the site has touch capability or not. Therefore we need to add something to the else statement in the Javascript. That's easily rectifided as shown in this example code -</p>
<p>if ('ontouchstart' in document.documentElement)
{
// It's a touch screen device.</p>
<p>// add claas of touch to container for the CSS 
$('#container').addClass('touch');</p>
<p>// create the button div
$('#container').prepend('<div id='nav-btn'></div>');</p>
<p>// make the button div a toggle show/hide$('#nav-btn').click(function(){
$('nav').toggle();
return false;
})
}</p>
<p>else 
{
// shown navigation menu
$('nav').css('display','block');
}</p>
<p>Here's an updated fiddle including all that fun code -</p>
<h2 id="it's-not-over-until-you-open-it-in-opera-mini" tabindex="-1">It's not over until you open it in Opera Mini</h2>
<p>Although I've managed to get this working in MobileSafari (iOS 5.1.1), a Android 2.2,2.2.1,2.3.6 and 4.0 browser and Opera Mobile. Opera mini was giving me a headache.</p>
<p>For some reason (to which I guess it's because it is a <a href="http://en.wikipedia.org/wiki/Opera_Mini">proxy browser</a>) Opera mini doesn't create the nav-btn div and prepend it to it's #container. Doing this means an Opera mini user won't see the menu AT ALL unless they've got JavaScript disabled.</p>
<p>Having a quick hunt around the internet I found that you can target the browser using JavaScript. So adding this code would then give you the links back, but with out the additional styling also. If you wanted you could then define these again with another class and apply that too. But for now -</p>
<p>if (operamini)
{
// remove .touch class for opera mini as it can't create the #nav-btn element
$('#container').removeClass('touch');
}</p>
<p>else
{</p>
<p>}</p>
<h2 id="that's-all-folks!" tabindex="-1">That's all folks!</h2>
<p>There we pretty much have it, a menu button that's created with CSS added with JavaScript that if enabled alse changes the styling of your navigation to suit your touch enabled device and your fat fingers.</p>
<p>Here's one last fiddle -</p>
<p>But if you want to go straight to a page just to test it on your device(s) then I've hosted it on <a href="http://alwaystwisted.com/playground/1.html">my site here</a> too.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Create a pure CSS menu button</title>
      <link href="https://www.alwaystwisted.com/articles/create-a-pure-css-menu-button.html"/>
      <updated>2012-05-12T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/create-a-pure-css-menu-button.html</id>
      <content type="html">
        <![CDATA[
        <h1 id="part-1-of-a-series-looking-at-progressively-enhanced%2C-mobile-first%2C-reponsive-navigation" tabindex="-1">Part 1 of a series looking at progressively enhanced, mobile first, reponsive navigation</h1>
<p>If you've <a href="http://twitter.com/sturobson">followed me</a> on the twitters for some time, you'll know my thoughts on the <a href="http://stuffandnonsense.co.uk/blog/about/we_need_a_standard_show_navigation_icon_for_responsive_web_design">best solution</a> for <a href="http://bradfrostweb.com/blog/web/responsive-nav-patterns/">mobile navigation</a>. In short. I hate the idea of using a <a href="http://www.stuffandnonsense.co.uk/blog/about/the_select_menu_navigation_pattern"><select></a> to 'fix' your navigation. Although it's a great idea that's been <a href="https://github.com/mattkersley/Responsive-Menu">created</a>. I feel that the extra 'tap' to select the link, the inherent difference in styling and implementation across devices make me believe that -</p>
<blockquote>
<p>Using <select> for mobile navigation is a developer's answer to a designer's problem.</p>
</blockquote>
<p>Now, I've also been thinking about how much we should be thinking about what we're actually giving the person with their (insert any handheld mobile device but) iPhone.</p>
<h2 id="some-options." tabindex="-1">Some options.</h2>
<p>You see, creating a new image for the menu icon could create another http request (although you could (and should) create a css sprite of  'ALL THE THINGS' like that, but you would still have that extra kb to download).</p>
<p>You could use a <a href="http://css-tricks.com/examples/IconFont/">icon font</a>, but again this would create another http request and also a file of which you don't use all of it's parts. Although it can scale nicely (or <a href="http://simurai.com/post/19895985870/icon-sharpness-limbo">not</a>) for a menu button for your handheld touch device it's a little overkill.</p>
<h2 id="door-number-3." tabindex="-1">Door number 3.</h2>
<p>I think, one way of creating your 3 line mobile navigation menu button is to use CSS. Pure CSS. It'll add a few lines of code to your CSS file but would be a little nicer for your user to not have to download more stuff just for one button.</p>
<p>So to create a simple 3 line menu button you'd need to write something akin to this -</p>
<p>HTML</p>
<p><div id='lines'></div></p>
<p>CSS</p>
<p>#lines { 
    border-bottom: 17px double black; 
    border-top: 6px solid black; 
    content:'';
    height: 5px; 
    width:30px;
}â€‹</p>
<p>Result</p>
<p>Now, the only issue with creating something like this is an empty div, that's pretty crappy but I'll get to that in a later post. Let's just concentrate on creating cool CSS only menu buttons.</p>
<p>Maybe for this we want to add a border around it to make it 'look' more like a button. We can do this by adding a class to the <div> and changing around the CSS to include a :before rule.</p>
<p>HTML</p>
<p><div id='lines' class='btn'></div></p>
<p>CSS</p>
<p>.btn {
position: relative;
margin-top:2%;
border: 2px solid black;
border-radius: 2px;
height: 36px;
width:36px;
}
#lines:before {
border-bottom: 17px double black;
border-top: 6px solid black;
content:'';
height: 5px;
position: absolute;
right:3px;
top: 4px;
width:30px;
}</p>
<p>Result</p>
<p>Here you can see we've added a border around the lines with the class .btn. Doing it this way means that any css rules for #lines would overide them. Therefore we've used the :before pseudo selector to achieve a nice result.</p>
<h2 id="there's-more%3F" tabindex="-1">There's more?</h2>
<p>Of course there's more. Although I love the 3 lines menu, after a recent discussion on twitter, it won't really work if you're having sub navigation within the main navigation. Lots of 3 line icons all stack on each other it can get confusing . So I created some more buttons out of CSS.</p>
<h2 id="build-it%2C-break-it%2C-make-more" tabindex="-1">Build it, Break it, Make More</h2>
<p>As you can see the CSS icons are up on jsfiddle. Have a look, take them apart, make them better, make them sexier and add them to the comments.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>CSS navigation with diagonals</title>
      <link href="https://www.alwaystwisted.com/articles/css-navigation-with-diagonals.html"/>
      <updated>2012-05-07T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/css-navigation-with-diagonals.html</id>
      <content type="html">
        <![CDATA[
        <p><img src="/images/articles/screen-shot-20120507-at-20.05.25-ck.png" alt="" loading="lazy" decoding="async"></p>
<p>Sometimes when I look at the twitters i find little requests for ideas on how to do something. I often do this to, usually for jQuery. Today <a href="http://twitter.com/markskinner_">Mark Skinner</a> wondered this -</p>
<blockquote>
<p>Any suggestions on how to achieve <a href="http://t.co/OHG1ZpK8" title="http://work.kevinleary.net/diagonal-nav/diagonal-navigation-setup.html">work.kevinleary.net/diagonal-nav/d…</a> without using the JQuery? :-)</p>
<p>— Mark Skinner (@MarkSkinner_) <a href="https://twitter.com/MarkSkinner_/status/199425235118854144">May 7, 2012</a></p>
</blockquote>
<p>As soon as I clicked the link I instantly thought that a navigation system (menu) like this could be created in pure CSS</p>
<p>I found myself with a free half hour so I thought I'd crack open <a href="http://jsfiddle.net">JSFiddle</a> and have a go to see what I could come up with. Please note: there are other online <a href="http://dabblet.com/">places</a> and <a href="http://codepen.io/">spaces</a> to quickly code up simple things, I just am so used to the 4 windows of JSFiddle it's hard to try anything else (for now).</p>
<h2 id="the-code-begins." tabindex="-1">The Code Begins.</h2>
<p>First up I obviously needed to create the HTML for the menu. I knew in my CSS I was going to be using display: inline-block; on the <li> elements so I wrote this example HTML.</p>
<ul>
    <li><a href=''>link 1</a><li>
    <li><a href=''>link 2</a></li>
    <li><a href=''>link 3</a></li>
    <li><a href=''>link 4</a></li>
<ul>
<p>What i did to the above examples was put all the <li> elements on a single line of code. Simliar to this -</p>
<ul>
    <li><a href=''>link 1</a><li><li><a href=''>link 2</a></li>
</ul>
<p>By putting the <li> in one line with no gaps we would not inherit a 4px gap that inline-block gives us by proxy.</p>
<h2 id="css-set-up." tabindex="-1">CSS Set-up.</h2>
<p>For years I've used <a href="http://twitter.com/meyerweb">Eric Meyer's</a> CSS <a href="http://meyerweb.com/eric/tools/css/reset/">Reset</a> in the various guises it pulled and only recently (the last 3-4 months) have I side-lined it for <a href="http://twitter.com/necolas">Nicolas Gallagher's</a> <a href="http://necolas.github.com/normalize.css/">Normalize</a> system. So first off this is including in pretty much every CSS file I create and (luckily) it's also included in new default JSFiddle page.</p>
<p>Secondly I now add the new cool box-sizing CSS property which that <a href="http://twitter.com/paulirish">Paul Irish</a> discusses in this <a href="http://paulirish.com/2012/box-sizing-border-box-ftw/">blogpost</a>.</p>
<p>* {
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit <em>/
-moz-box-sizing: border-box; /</em> Firefox, other Gecko <em>/
box-sizing: border-box; /</em> Opera/IE 8+ */
}</p>
<h2 id="and-to-start." tabindex="-1">And to start.</h2>
<p>Next I wrote a little bit of CSS. This would be to style the <ul> and the <li> elements and can be changed to suit -</p>
<p>ul {
background: grey;
height: 60px;
padding: 10px 0 10px 40px;
width: 100%;
}</p>
<p>li {
background: orange;
float: left;
line-height: 20px;
margin-right: 30px;
padding: 10px 3px;
position: relative;
}</p>
<p>As you can see I've added a margin-right to all the</p>
<p>elements so I need to tidy that up a bit with some CSS3 Pseudo Selectors. This would be just to remove the last margin-right property from the last element-</p>
<p>li:last-of-type { margin-right: 0px; }</p>
<h2 id="triangles" tabindex="-1">Triangles</h2>
<p>Ok, so now that each navigation element has a 'block' of colour I wanted to start adding the 'diagonal' parts to it. To do this with CSS I used the :before and :after elements of CSS 2.1 and created this bit of code -</p>
<p>li:before {
background: none;
border-left: 20px solid transparent;
border-right: 0px solid transparent;
border-top: 40px solid orange;
content: '';
left: -20px;
position: absolute;
top: 0;
}</p>
<p>li:after {
border-left: 0px solid transparent;
border-right: 20px solid transparent;
border-bottom: 40px solid orange;
content: '';
height: 0;
position: absolute;
right: -20px;
top: 0;
width: 0;
}</p>
<h2 id="hover" tabindex="-1">Hover</h2>
<p>So, as it's a little bit of navigation it's best that I add some kind of hover effect to it. To do this there's some funky CSS that need's to be added so the whole kaboodle will change colour on hover.</p>
<p>First off we add display: block; to the <a> element, we might as well get rid of that nasty text-decoration too -</p>
<p>a {
color: black;
display: block;
text-decoration: none;
}</p>
<p>Now we've done that we can just change the bits we need to change for the hover effect. This would be for the actual <li> element and it's :before and :after pseudo bits too.</p>
<p>li:hover {
background: white;
cursor: pointer;
}
li:hover:before {
border-top: 40px solid white;
}
li:hover:after {
border-bottom: 40px solid white;
}</p>
<p>As you can see I've '<a href="http://www.w3.org/TR/CSS2/selector.html#selector-syntax">stacked</a>' the pseudo selectors 'on top' of each other so that when 'hovered over' the whole dang thing changes colour.</p>
<h2 id="we-could-have-finished-there." tabindex="-1">We could have finished there.</h2>
<p>Looking back at the original link Mark tweeted we can see that the first link (home) doesn't have a diagonal on the left only on the right. So to create this effect we need to add this bit of CSS -</p>
<p>li:first-of-type:before {
background: orange;
border: none;
height: 40px;
left: -10px;
width: 10px;
}</p>
<p>li:first-of-type:hover:before {
background: white;
height: 0px;
width: 10px;
}</p>
<p>This removes the border which was making the triabgle and adds a simple rectangle of colour</p>
<h2 id="a-step-roo-far%3F" tabindex="-1">A Step roo far?</h2>
<p>After doing this quickly I though it'd be nice to 'finish off' the navigation's design with a similar effect to the last</p>
<p>element. Just like this -</p>
<p>li:last-of-type:after {
background: orange;
border: none;
height: 40px;
right: -10px;
width: 10px;
}
li:last-of-type:hover:after {
background: white;
height: 40px;
width: 10px;
}</p>
<h2 id="that's-about-it." tabindex="-1">That's about it.</h2>
<p>Doing all this has created a nice little CSS navigation effect.</p>
<p>Of course there are some gotcha's.</p>
<ol>
<li>It's not 'responsive', I'm of the thinking that you'd switch up the styling of navigation for smaller viewports anyway so this wouldn't be a problem.</li>
<li>It can break, of course it can. If the menu is longer  than the viewport, it'll break. I may refine this bit. I may not.</li>
</ol>
<p>I've tidied it up a little bit and the <a href="http://jsfiddle.net/sturobson/Xxxvd/">final JSFiddle</a> is available to look around and poke at.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Everyday I&#39;m Bubbling. With Media Queries and LESS</title>
      <link href="https://www.alwaystwisted.com/articles/everyday-im-bubbling-with-media-queries-and-less.html"/>
      <updated>2012-05-05T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/everyday-im-bubbling-with-media-queries-and-less.html</id>
      <content type="html">
        <![CDATA[
        <p>We're all in love with <a href="http://adactio.com/journal/4523/">content first</a>, <a href="http://www.abookapart.com/products/mobile-first">mobile first</a>, insert your buzzword of choice, <a href="http://www.abookapart.com/products/responsive-web-design">responsive web design</a> aren't we? We all know that we <a href="http://alwaystwisted.com/post.php?s=2012-04-28-a-common-set-of-breakpoints-to-start">should</a> (or <a href="http://adactio.com/journal/5425/">shouldn't</a>) be using common <a href="http://css-tricks.com/snippets/css/media-queries-for-standard-devices/">breakpoints</a>.</p>
<p>We also know that we should be doing what <a href="https://twitter.com/stephenhay">Stephen Hay</a> puts so eloquantly -</p>
<blockquote>
<p>'Start with the small screen first, then expand until it looks like shit. Time to insert a breakpoint!'</p>
</blockquote>
<p>Now, we could just add that new media query breakpoint in our CSS with it's relevant min-width and even with it's max-width point like we have since we've started using media queries. Or we could get bubbling.</p>
<h2 id="pretty-bubbles-in-the-air." tabindex="-1">Pretty Bubbles in the air.</h2>
<p>With an update to <a href="https://github.com/cloudhead/less">LESS</a> in <a href="https://github.com/cloudhead/less.js/pull/634">February</a>. <a href="https://twitter.com/#!/cloudhead">Alexis</a>, the creator of LESS, included media query bubbling from a pull request. This means you can now write your LESS code with the media query within the element and when you compile it'll create a seperate media query for each one you create. So, you would now write your LESS like this -</p>
<p>header {
color: red;</p>
<p>@media only screen and (min-width : 768px) { color: green; }</p>
<p>@media only screen and (min-width : 1024px) { color: blue; }</p>
<p>}</p>
<p>section {
color: green;</p>
<p>@media only screen and (min-width : 768px) { color: blue; }</p>
<p>@media only screen and (min-width : 1024px) { color: red; }</p>
<p>}</p>
<p>After doing all our LESS like this and compiling it, it will create this, for the above example -</p>
<p>header {
color: red;
}
@media only screen and (min-width: 768px) {
header {
color: green;
}
}
@media only screen and (min-width: 1024px) {
header {
color: blue;
}
}</p>
<p>section {
color: green;
}
@media only screen and (min-width: 768px) {
section {
color: blue;
}
}
@media only screen and (min-width: 1024px) {
section {
color: red;
}
}</p>
<p>As you can see it creates a seperate media query for whatever has a media query. It doesn't 'group' them all together as we currently do when coding by hand.</p>
<p>I can see a real benefit of this being created in your stylesheet, as you can see easily what elements are being changed by what media query and how at a glance. This could be more difficult when your media queries are in seperate styleshets or in 'big chunks' or media queries.</p>
<p>Another benefit would be when we go back and look at Stephen's quote. When your design starts to 'look shit'  using this technique would be just that little be cleaner and quicker to do.</p>
<p>I've yet to do any performance or 'stress' tests on actual CSS files created this way rather than the 'big chunks' we've been creating thus far but hope to do this soon.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>The Horse Has Bolted... -o-really?</title>
      <link href="https://www.alwaystwisted.com/articles/the-horse-has-bolted-o-really.html"/>
      <updated>2012-05-03T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/the-horse-has-bolted-o-really.html</id>
      <content type="html">
        <![CDATA[
        <p>Ok, so we all know about what Opera are now <a href="http://dev.opera.com/articles/view/opera-mobile-emulator-experimental-webkit-prefix-support/">up to</a>. It's too late to continue the pontification, conjecture and gesticulation of how <a href="http://www.stuffandnonsense.co.uk/blog/about/there_i_said_it">they're wrong</a> in doing it or should be <a href="http://mattwilcox.net/archive/entry/id/1087/">doing it this way</a>. It's too late, that boat has set sail, the rocket has launched, the horse has bolted.</p>
<p>If you didn't inlude all the relevant vendor prefixes, or only included webkit's, you're an idiot. But let's not worry about that now. Let's try and build for the future.</p>
<h2 id="so-what-now%3F" tabindex="-1">So What Now?</h2>
<p>Fortunately there are lots of options, which is really good. A great choice surrounds us in prefixing the shit out of your CSS3.</p>
<p>If you, like me (currently), code your CSS up 'dry' without a preproccesor there are several online CSS3 generators that will create the appropriate prefixed CSS for the relevant property.</p>
<h2 id="to-start." tabindex="-1">To Start.</h2>
<p>CSS3 is one part of my stylesheet that I tend to write the most cleanly (in my opinion) so that it's a breeze to edit all of those prefixes as quickly as possible. Here's how I code a CSS3 property -</p>
<p>.element {
-webkit-transition: all 0.3s ease-out;  /* Saf3.2+, Chrome <em>/
-moz-transition: all 0.3s ease-out;  /</em> FF4+ <em>/
-ms-transition: all 0.3s ease-out;  /</em> IE10 <em>/
-o-transition: all 0.3s ease-out;  /</em> Opera 10.5+ */
transition: all 0.3s ease-out;
}</p>
<p>Here I've got all of the prefixes in order of property name length finally followed by the non-prefixed version. This was when a browser depreciates their prefixed version (usually when the property is stable enough in the spec.) the latest browser version will see the non-prefixed version last and override any prefixed version.</p>
<h2 id="talking-'bout-my-generators" tabindex="-1">Talking 'bout my Generators</h2>
<p>So, if you are someone who likes just typing the code in without a preprocessor you're in good luck. There are loads of CSS3 generators that can help you use the correct prefixed CSS for the property you're wanting to use. You'd go to this kind of site, do your thing, copy, go back to your editor of choice and paste. Done. You've added the correct CSS3 prefixed to the hilt, ready to fight.</p>
<p>Here's a few choice ones to use -</p>
<ol>
<li><a href="http://www.css3.me/">www.css3.me</a> - a CSS3 generator for border-radius, box-shadow, background gradients and opacity.</li>
<li><a href="http://css3please.com/">css3please.com</a> - all the CSS3 properties with editing in the browser to see what happens to the demo element.</li>
<li><a href="http://css3generator.com/">css3generator.com</a> - this is the one I use, almost daily. Nice and big for my ageing eyes.</li>
<li><a href="http://www.css3maker.com/index.html">www.css3maker.com</a> - another generator for multiple CSS3 properties which also adds appropriate CSS 2.1 properties that you may use at the same time.</li>
<li><a href="http://www.colorzilla.com/gradient-editor/">www.colorzilla.com/gradient-editor</a> - a generator for just those pesky gradients. The bastard child of CSS3 that'll make anyones stylesheet look ugly.</li>
</ol>
<h2 id="less-is-more%3F" tabindex="-1">LESS is more?</h2>
<p>If you're a LESS user, the easiest thing you can do is include <a href="http://lesselements.com/">LESS Elements</a>, if you look at the page, all you gotta do is write the CSS3 property once in LESS and when it's complied it'll add all the prefixed fun for you. Be sure that you've got the <a href="https://github.com/dmitryf/elements">latest version</a>.</p>
<p>Another option is <a href="https://github.com/danethurber/seamLESS">seamLESS</a>.</p>
<h2 id="you're-so-sass-y!" tabindex="-1">You're so SASS-y!</h2>
<p>If you like your CSS preprocessed <a href="http://thesassway.com/">The SASS Way</a> then there are two options I've been informed of by some lovely friends on the twitters. You could try <a href="http://compass-style.org/">Compass</a> or <a href="http://thoughtbot.com/bourbon/">Bourbon</a>. Just for the name, I beseech you to use Bourbon.</p>
<h2 id="prefixme." tabindex="-1">PrefixMe.</h2>
<p>If you want to write your CSS dry but don't want to add all those prefixes in by hand or by copying and pasting you could use that Lea Verou's <a href="http://leaverou.github.com/prefixfree/">Prefix free</a> where adding a 2kb file and you're ready to go. Of course there's the extra HTTP request and reliance on JavaScript to consider there too.</p>
<h2 id="what-next%3F" tabindex="-1">What next?</h2>
<p>I don't know, what I do know is that if you're not including all the relevant prefixes that are possibly required for the CSS3 property you want to use you are being disingenous to your craft and tarnishing us all with the same brush and fate that leads to actions like that taken by Opera.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>When your viewport lies...</title>
      <link href="https://www.alwaystwisted.com/articles/when-your-viewport-lies.html"/>
      <updated>2012-04-29T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/when-your-viewport-lies.html</id>
      <content type="html">
        <![CDATA[
        <p>You may be aware that a while back when that <a href="http://twitter.com/stephanierieger">Stephanie Rieger</a> posted <a href="http://stephanierieger.com/strategies-for-choosing-test-devices/">'Strategies for choosing test devices'</a> I decided to throw up a simple tumblr blog with developer's <a href="http://mytestsuite.tumblr.com/">device testing suite</a> (please add yours so that there'd be a small resource for helping others to decide what to buy.</p>
<p>About the same time I started researching and purchased a Samsung Galaxy Europa on the magical eBay. There really is a bargain to be had if you look hard enough. I managed to get this for a bargain price of £35.</p>
<h2 id="a-back-story" tabindex="-1">A back story</h2>
<p>Also at the same time I was embarking on a 120 hour project for a start up I'm now a co-founder of where, initially, I was the front-end developer turning the PSD's into a nice HTML/CSS/jQuery web system for the back-end to 'plug into'.</p>
<p>During the many skype conversations I managed to get agreed an attempt at an 'responsive' version of the fixed width designs.</p>
<h2 id="what-did-i-just-buy%3F" tabindex="-1">What did I just buy?</h2>
<p>So in the preliminary coding of the designs I thought I'd check it out on my Android device (the Eurpoa). When I ordered the mobile I knew that it'd be a device that was 240px wide and 320px high (in portrait). I thought that it'd be great to have that because there's quite a few devices that have this screen size.</p>
<p>What I wasn't expecting was for it to 'spoof' itself in thinking that it's actual viewport is 320x401 (in portrait). This makes everything a lot smaller. My hands are not the chubbiest of things and it's a real difficulty in typing in a domain name so 'pushing' buttons and navigating around a site that's 'smaller' because of this was kinda hard.</p>
<h2 id="real-devices" tabindex="-1">Real devices</h2>
<p>So case in point. It really is benificial to <a href="http://bradfrostweb.com/blog/mobile/test-on-real-mobile-devices-without-breaking-the-bank/">'test on a real device'</a>. Without doing this I could have made potential users struggle.</p>
<h2 id="human-interface-guidelines" tabindex="-1">Human Interface Guidelines</h2>
<p>I'm a real big fan of Apples <a href="http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/MobileHIG/Introduction/Introduction.html">guidelines</a>, although aimed for iOs applications I think that a lot of it's 'sizing of things' can be carried across to your small/narrow/mobile/device viewport designs. Also worth a read is this fantastic article about the <a href="http://aentan.com/design/new-visual-proportions-for-the-ios-user-interface/">visual proportions of iOS</a>. Of course, again, these guidelines are for a specific 'fixed width' kind of design but a lot of it can carry over within your responsive development even if device viewports can be quite an <a href="http://stephanierieger.com/the-trouble-with-android/">accumalation</a>.</p>
<h2 id="so%2C-be-careful-out-there" tabindex="-1">So, be careful out there</h2>
<p>Just because it works on your iPhone, it maybe squashed on a smaller viewport (or a smaller device lying to you), testing in the browser is great for the intial part of your responsive tool kit but try and get that design tested on as many devices as you can as often as you can. Your viewport maybe different to what you perceive.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A common set of breakpoints to start</title>
      <link href="https://www.alwaystwisted.com/articles/a-common-set-of-breakpoints-to-start.html"/>
      <updated>2012-04-28T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-common-set-of-breakpoints-to-start.html</id>
      <content type="html">
        <![CDATA[
        <p>On Thursday (26/04/12) the fantabulous <a href="http://twitter.com/adactio">Jeremy Keith</a> wrote a short post on <a href="http://adactio.com/journal/5425/">common breakpoints</a> in responsive web design where he expands his thoughts on a question asked to <a href="http://twitter.com/beep">Ethan Marcotte</a> in a <a href="http://www.netmagazine.com/interviews/ethan-marcotte-answers-your-responsive-web-design-questions">Q&amp;A article</a> on the .net magazines's website.</p>
<p>Ethan was asked -</p>
<blockquote>
<p>'What devices (smartphones/tablets) and breakpoints do you typically develop and test with?'</p>
</blockquote>
<p>His retort can be summed up just by the last sentence of the response -</p>
<blockquote>
<p>'...we should focus on breakpoints tailored to the design we’re working on.'</p>
</blockquote>
<p>Where as I completely agree that we shouldn't be just 'designing' sites for specific devices. For me it's quite hard to not think about how something would look on a popular device viewport.</p>
<h2 id="how-i-like-it..." tabindex="-1">How I like it...</h2>
<p>As I'm a freelance front-end developer that codes by candlelight I'm sure you can understand I don't work (well, not yet) on too many really big projects I generally think out most of my designs rather than initially draw a wireframe / open up photoshop. Doing this I tend to 'think' how the design would look on my iPhone and my iPad and my MacBook Air (yes, I use Apple products).</p>
<p>Therefore I always start with a 'boilerplate' of media queries. They're aren't a hard and fast of rules to stick to, just a starting point. Of course the first starting point when coding a design is as perfect as <a href="https://twitter.com/bryanrieger">Bryan Rieger</a> puts it</p>
<blockquote>
<p>The lack of a media query is your first media query</p>
</blockquote>
<p>So I do all of my basic stuff here, all the typography stuff, things like that before I even get to a media query. Then after that I start designing (well, coding?) with this list of <a href="http://app.kodery.com/s/1075">basic media queries</a> -</p>
<p>/* ===== == = === Base Styles === = == ===== */</p>
<p>/* ===== == = === 20em (320px) === = == ===== */</p>
<p>@media only screen and (min-width : 20em) {
}</p>
<p>/* ===== == = === 30em (480px) === = == ===== */</p>
<p>@media only screen and (min-width : 30em) {
}</p>
<p>/* ===== == = === 37.5em (600px) === = == ===== */</p>
<p>@media only screen and (min-width: 37.5em) {
}</p>
<p>/* ===== == = === 48em (768px) === = == ===== */</p>
<p>@media only screen and (min-width : 48em) {
}</p>
<p>/* ===== == = === 56.25em (900px) === = == ===== */</p>
<p>@media only screen and (min-width : 56.25em) {
}</p>
<p>/* ===== == = === 68.75em (1100px) === = == ===== */</p>
<p>@media only screen and (min-width : 68.75em) {
}</p>
<p>/* ===== == = === 81.25em (1300px) === = == ===== */</p>
<p>@media only screen and (min-width : 81.25em) {
}</p>
<h2 id="em%2C-how-many%3F" tabindex="-1">Em, How many?</h2>
<p>I lied, it's not really basic it's slightly more than that. Once I've designed (well, coded) with some or all of these breakpoints I then start getting my resizing thing down. For me that's the key bit. Not where or when you include your media query 'breakpoints' in earnest, but what goes in between.</p>
<blockquote>
<p>'Start with the small screen first, then expand until it looks like shit. Time to insert a breakpoint!'</p>
</blockquote>
<p>Although I don't follow <a href="https://twitter.com/stephenhay">Stephen Hay's</a> words to the letter, the next part along my design(coding?) process is to resize the browser until it 'looks like shit' then I'll add a breakpoint to fix it. I may even add a min-width and a max-width rule, or a max-width rule. Whatever works to make the design look nice at any viewport size, as best I can. Don't forget to test on as many devices as possible either.</p>
<p>You'll also not I'm using <a href="http://blog.cloudfour.com/the-ems-have-it-proportional-media-queries-ftw/">ems for my breakpoints</a> instead of px. This helps for users who zoom and ties your media queries more to the design than device viewport.</p>
<h2 id="but%2C-what-about-the-future%3F" tabindex="-1">But, what about the future?</h2>
<p>How long in the future are we going? Well as phones are being released (well, Android OS'd ones) faster than you can say Jack Robinson so are list of possible viewport sizes we're going to have to deal with but there are still going to be more popular devices that'll (I'm in) know doubt will keep to roughly the same pixel screen resolutions they do at the moment, if not a few years to come (in the future).</p>
<h2 id="content-first%3F" tabindex="-1">Content first?</h2>
<p>Well, content blocks first. My expectations of a client to deliver everything I need before I start are unfortunately not going to be delivered soon. The project I was working on January - March (sshhhh, we're still working on it) this year had content that would have been provided by it's users so I had to work with what the content could be expected to look like and where it would go etc. This worked, it worked just fine. I'd love every word to be presented, that's not going to happen, nor should it. The web is a breathing beast, so is it's content.</p>
<h2 id="my-point." tabindex="-1">My Point.</h2>
<p>I don't think that having a set of 'common' media queries harms your desiging of a site as long as you resize that bad boy and fix anything that looks shit. Like all things I do when I'm coding though, this idea is subject to change.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Adding a class with JavaScript, The Results</title>
      <link href="https://www.alwaystwisted.com/articles/adding-a-class-with-javascript-the-results.html"/>
      <updated>2012-04-27T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/adding-a-class-with-javascript-the-results.html</id>
      <content type="html">
        <![CDATA[
        <p><img src="/images/articles/1335556810untitled1-ck.jpg" alt="I god damn changed my mind, yes I did." loading="lazy" decoding="async"></p>
<p>Yesterday I wrote about how I'm <a href="http://alwaystwisted.com/post.php?s=2012-04-26-nojs-no-i-like-hasjs">adding a HasJS class to the HTML</a> element in my designs rather than swapping out a no-js class or removing a no-js class.</p>
<p>i'd originally thought that the best way (well the only way I originally thought of) was to add -</p>
<p><code>$('html').addClass('hasJS');</code></p>
<p>to my script.js of my (work in progress) personal, personable boilerplate.</p>
<p>Soon after realising that blogpost to the world <a href="http://allmarkedup.com/">Mark Perkins</a> added a comment saying that add this -</p>
<p><script>document.getElementsByTagName('html')[0].className += ' hasJS';</script></p>
<p>added in the head would be a better/quicker way of doing it. I also had a couple of comments via the twitters saying this too.</p>
<h2 id="testing%2C-testing...1%2C-2%2C-3" tabindex="-1">Testing, Testing...1, 2, 3</h2>
<p>So I decided today that what better way to spend a Friday evening that test those two bits of code with JSPerf. Now, in all honesty, I don't know what I'm doing. But, Sshhhh!!!. So I managed to find a test that already tested the performance for JavaScript to add a class with jQuery and 'Modern Javascript'. I thought this was perfect and also added the code that Mark offered and ran some tests.</p>
<h2 id="whaaaatt%3F%3F%3F" tabindex="-1">Whaaaatt???</h2>
<p>Whilst I was testing all the browsers I've got on my MBA I thought it best to open up my Parallels VMWare and run it in IE9 (to start). Here's where I hit a problem with one of the tests. So I thought I'd do what I often do <a href="http://twitter.com/jack_franklin">'Ask Jack'</a>.</p>
<p>He pointed to a <a href="https://developer.mozilla.org/en/DOM/element.classList">Mozilla Dev page</a> which shows that IE (until v10) doesn't support -</p>
<p>classList</p>
<p>On that page is a nice <a href="https://github.com/eligrey/classList.js/blob/master/classList.js">polyfill for IE8 and up</a> so I 'shoved' that into that test code and re-ran the tests.</p>
<h2 id="near-the-finish-line..." tabindex="-1">Near the finish line...</h2>
<p>Here's the <a href="http://jsperf.com/modern-js-vs-jquery-add-class/3">results</a> for the test I re-ran with the polyfill included.</p>
<p><img src="/images/articles/1335556227screenshot20120427at20.47.01-ck.png" alt="" loading="lazy" decoding="async"></p>
<p>As you can see the modern JS approach is quickest by miles. So I've decided (subject to change) that I'm now going to include -</p>
<p>document.querySelector('html').classList.add('js');</p>
<p>into the HEAD of my personal, personable boilerplate.</p>
<h2 id="just-one-more-thing" tabindex="-1">Just one more thing</h2>
<p>You may noticed that I've also ditched .hasJS for just .js for my class name. This was spurred on from a brief couple of tweets with <a href="http://twitter.com/mattwilcox">Matt Wilcox</a> that made me decide that losing those three charecters will shave at least a little off my stylesheet file size. Every little helps and all that. That's about it for this post. You know, tomorrow is a different day. I may change my mind all over again. I'm currently trying to work out how to conditionally load the polyfill if <code>classList</code> is not supported. Until then, good 'morrow</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>no-js? No, I like hasJS</title>
      <link href="https://www.alwaystwisted.com/articles/no-js-no-i-like-hasjs.html"/>
      <updated>2012-04-26T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/no-js-no-i-like-hasjs.html</id>
      <content type="html">
        <![CDATA[
        <p><img src="/images/articles/untitled1-ck.jpg" alt="my boilerplate, made by me" loading="lazy" decoding="async"></p>
<p>I last looked at my 'boilerplate' in January. It was before a long 120 hours of front end development for a product myself and my now co-founders are still working on. But I digress.</p>
<p>What I did at the time was download both the <a href="http://html5boilerplate.com/">HTML5 Boilerplate</a> and Andy Clarke's <a href="http://stuffandnonsense.co.uk/projects/320andup/">320&amp;Up</a> Framework. I went through every line of code, deleting bits I didn't want to include by default and changing other bits to more suit my asthetic needs (and change hot pink to a dark blue).</p>
<p>After doing this whilst coding the sight I wanted to progressively enhance the design (as you do) so that it'd work great with JavaScript (well jQuery) off or on.</p>
<p>I initially left the no-js tag in the html class in the html template and decided to swap it out and replace it with hasJS if the user has JavaScript enabled. After demoing my code via the twitters someone asked why I'm swapping out no-js and replacing it. After this I chose to only add the hasJS tag to the HTML document if the user has JavaScript enabled.</p>
<p>This way, for me I'm progressively enhancing what I'm doing. The code is all lovely and clean and if parts of the design make use of jQuery I only have to add a .hasJS to that particular div/article/nav/ul/whatever in the CSS. It works for me, it may not work for you. Like all things, we all have a preference to what ever options there are.</p>
<p>So here's what I do -</p>
<p>In my scripts.js file I now have this at the top of the code -</p>
<p>$('html').addClass('hasJS');</p>
<p>Then whenever I want some of my fantastically clean CSS to be changed because I'm now doing something a little different because of the jQuery I'd do this -</p>
<p>article { background-color: red; }</p>
<p>.hasJS article { background-color: pink; }</p>
<p>This way when the jQuery kicks into play it'll change the background-color, when it's not working it'll stay red.</p>
<p>Note, I don't use Modernizr, so any benefit the no-js class had with this is lost on me. This is how I do it and it goes with my belief that my boilerplate is mine, it's for me, it helps me how I work. It may be taking bits from here and there but it's be refactored to how I want it. This is just one of the decisions I've made in making my boilerplate. I hope to blog more on anything else that I've changed/edited/deleted or added to my boilerplate soon too.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Listen, everyday...</title>
      <link href="https://www.alwaystwisted.com/articles/listen-everyday.html"/>
      <updated>2012-04-07T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/listen-everyday.html</id>
      <content type="html">
        <![CDATA[
        <p>Web design, currently, is not my fulltime gig. I'm a project technician for a conference set design, construction and installation company. I live about 12 miles from work. Which gives me plenty of time during the day to listen to some podcasts.</p>
<p>There's fantastically been a glut of new podcasts as well as some that are little older because they're getting better and better. So I'm making a little list. Below are some new podcasts that I listen to regularly.</p>
<h3 id="let's-make-mistakes" tabindex="-1"><a href="http://muleradio.net/mistakes/">Let's Make Mistakes</a></h3>
<p>As of writing this blog, this podcast from <a href="https://twitter.com/mike_ftw">Mike Monteiro</a> and <a href="https://twitter.com/slowtext">Katie Gillum</a> of <a href="http://muledesign.com/">Mule Design</a> is in it's 40th episode. Amongst the fantastic banter between Katie and Mike they discuss a variety of design topics. A stalwart go to if I want to listen to something.</p>
<h3 id="the-industry-podcast" tabindex="-1"><a href="http://theindustry.cc/category/podcast/">The Industry Podcast</a></h3>
<p>Only coming into episode 3 of a nice little podcast discussing web design and what's been 'going on' with, so far, a special guest each week.  One to definitely add to your itunes podcast list.</p>
<h3 id="shoptalk-show" tabindex="-1"><a href="http://shoptalkshow.com/">Shoptalk Show</a></h3>
<p>From <a href="http://twitter.com/chriscoyier">Chris Coyier</a> and <a href="http://daverupert.com/">Dave Rupert.</a> A weekly show that's just coming into double figures. A great chat with other indusry folks answering listener questions. Usually discussiing one 'topic' a week depending on the guest.</p>
<h3 id="the-east-wing" tabindex="-1"><a href="http://theeastwing.net/">The East Wing</a></h3>
<p>Another new weekly podcast, this time bought to you by <a href="http://timothybsmith.com/">Tim Smith</a>. A weekly 'interview' style show discussing the guests career, thoughts on the industry and things that have happened that week.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>My Favourite 5 Books</title>
      <link href="https://www.alwaystwisted.com/articles/my-favourite-5-books.html"/>
      <updated>2012-02-16T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/my-favourite-5-books.html</id>
      <content type="html">
        <![CDATA[
        <p>Like <a href="http://www.mikestreety.co.uk/2012/02/books-a-smashing-story/">@mikestreety</a>, I love the printed form factor of books. I've recently gone a little mental and purchased a whole slew of books (12 at the last count). Here's my current top 5.</p>
<ol>
<li><a href="http://shop.oreilly.com/product/0636920018100.do">Head First Mobile Web</a> [O'Rielly] {Mobile, CSS, HTML, JavaScript} - A great book to help you understand how we can design (well dev) for mobile devie and what pitfalls you will encounter. It's a great little (well  huge) book you can dip into or read from cover to cover.</li>
<li><a href="http://smacss.com/">SMACSS</a> [@snooka] {CSS} - This books gives insight to a system on how you can write your CSS to make a more manageable easy to use for your sites. I just still need to implement it. I cheated here as it's an eBook.</li>
<li><a href="http://www.abookapart.com/products/mobile-first">Mobile First</a> [A Book Apart] {Mobile} - A Book Apart make great little books. This from <a href="http://twitter.com/lukew">@lukew</a> is a must read for the modern web designer.</li>
<li><a href="http://shop.oreilly.com/product/9780596802455.do">CSS: The Missing Manual</a> [O'Rielly] {CSS} - For someone that took a haitus just as CSS was being developed in the browser wars of the 1990s when I came back to web design I needed to get some skills. This book was perfect for that. So easily readable and informative.</li>
<li><a href="http://www.sitepoint.com/books/mobile1/">Build Mobile websites and apps for smart devices</a> [sitepoint] {HTML, CSS, Design} - notice a theme? This has been a real help in creating the markup, layout and other code for a current project.</li>
</ol>
<p>As Iv'e got to number 5, loads of other books in my collection have come to mind. Both books from <a href="http://zomigi.com/">Zoe</a>, <a href="http://www.abookapart.com/products/responsive-web-design">Ethan's</a> book to name a few.</p>
<p>What's your top 5? Create a blog post and add it to the comments of Mike's <a href="http://www.mikestreety.co.uk/2012/02/books-a-smashing-story/">original post</a></p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A green light for productivity</title>
      <link href="https://www.alwaystwisted.com/articles/a-green-light-for-productivity.html"/>
      <updated>2012-02-05T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-green-light-for-productivity.html</id>
      <content type="html">
        <![CDATA[
        <p>I don't really DO todo lists. I love the idea of writing everything down that needs to be done and then ticking them off or putting a line through them when they're complete. But, when it comes to it. I'd rather spend that time on actually 'doing the work'.</p>
<p>I've generally kept mental todo list of everything that needs doing on the project that I'm working on but my current client asked for a list of what is left todo this weekend so I obliged.</p>
<p>In doing so I've created a basic little .doc file in pages. Now I happened upon an idea whilst typng this out.</p>
<p>Hopefully we all know about the red, amber and green traffic light system? Well that's what I'm applying to this clients todo list.</p>
<p>Basically everything that's entered is intitally coloured RED. When I make a start on something it gets changed and moved to AMBER. If it gets completed then it moves to GREEN. If it doesn't get completed additional notes are made as to what's left to do.</p>
<p>I'm in no doubt this is being employed by others. But I thought I'd add my little productivity finding with you on a dreary Sunday morning.</p>
<p>As for keep my todo list in my head. It'll still be there but I'll also be keeping this traffic light idea running too.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>An issue for &quot;one web&quot;</title>
      <link href="https://www.alwaystwisted.com/articles/an-issue-for-one-web.html"/>
      <updated>2012-02-01T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/an-issue-for-one-web.html</id>
      <content type="html">
        <![CDATA[
        <p>EDIT: This was originally titled 'an issue for responsive web design'. Thanks to <a href="http://twitter.com/faxtion">@faxtion</a> for pointing out that it was a crappy title.</p>
<p>Ok. This blog post may be brief. It'll no doubt be quite rambling. Let's face it, I'm from the West Country.</p>
<p>I'm currently working on a super exciting front-end project with a client who is all for the exciting new stuff of <a href="http://www.abookapart.com/products/responsive-web-design">responsive web design</a> and <a href="http://www.abookapart.com/products/mobile-first">mobile first</a>. It's brilliant, I'm super excited about what I'm working on and think it'll be aces.</p>
<p>You see I'm rambling.</p>
<h2 id="an-elephant%3F" tabindex="-1">An Elephant?</h2>
<p><img src="/images/articles/elephantintheroom-ck.png" alt="an elephant in the room" loading="lazy" decoding="async"></p>
<p>The possible problem arose today. We were discussing file uploads and all the fun that entails when I found out about a little problem with iOS.</p>
<p>Mobile Safari (as of writing) <a href="http://developer.apple.com/library/IOs/#documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html">does not support file upload</a>. So, that's quite a big problem there. You can build a fantastic website/app/juggernaut/sweet potato but you won't be able to upload anything to it from an iOS device. I think that's kind of a big deal.</p>
<p>I did a little searching on the tubes and found a little solution - <a href="http://code.google.com/p/iphone-photo-picker/">iPhone Photo Picker</a>. Admitedly as of writing this quick brain fart. I haven't looked into it with any real depth.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A LESS approach to &quot;Mobile First&quot; CSS &amp; supporting older IE browsers</title>
      <link href="https://www.alwaystwisted.com/articles/a-less-approach-to-mobile-first-css-supporting-older-ie-browsers.html"/>
      <updated>2011-12-01T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-less-approach-to-mobile-first-css-supporting-older-ie-browsers.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="update-10%2F01%2F12" tabindex="-1">Update 10/01/12</h2>
<p><a href="http://www.twitter.com/cloudhead">Alexis</a> has just tweeted with the release of <a href="https://gist.github.com/1591794">LESS 1.2.0</a> which he says now supports the first example in this blogpost. This is excellent news. As of writing this update the LESS CSS compiler has not updated yet, but give it a few days.</p>
<p><a href="http://twitter.com/necolas">Nicolas Gallagher</a> has recently written a <a href="http://nicolasgallagher.com/mobile-first-css-sass-and-ie/">fantastic post</a> about using SASS to aid you in giving legacy IE browsers a 'desktop' design whilst alse have a 'mobile first' approach in your stylesheets.</p>
<p>I don't like SASS, I prefer LESS. SASS to me is full of <a href="http://twitter.com/#!/StuRobson/status/118756553166823424">mirth</a>.</p>
<p>I set about creating myself a little framework of default files a while back that would use the LESS.app to compile my CSS before it's uploaded to the server.</p>
<p>(note: before we go any further, these following examples were tested using the latest version of the LESS.app)</p>
<h2 id="purely-fictional..." tabindex="-1">Purely Fictional...</h2>
<p>This is how I'd want it to work. It <a href="https://github.com/cloudhead/less.js/issues/122">currently doesn't</a> but hopefully will be sorted out soon...</p>
<p>I prefer the seperate stylesheets for seperate media queries approach and with LESS you can compile all of these into one CSS file for you site. This way you have a nice working enviroment with defined LESS files for defined breakpoints.</p>
<p>Although every project is different this would be my default list of LESS files -</p>
<ul>
<li>default.LESS</li>
<li>320.LESS</li>
<li>480.LESS</li>
<li>768.LESS</li>
<li>960.LESS</li>
<li>1200.LESS</li>
</ul>
<p>I also have a LESS file which I call styles.LESS which looks like this -</p>
<p>/* styles.css */</p>
<p>@import 'default';
@media (min-width:320px) {
@import '320';
}
@media (min-width:480px) {</p>
<p>What this does is pretty simple, using the LESS.app it takes the .LESS files in the list and compiles them into this CSS syntax in a file called styles.css -</p>
<p>@media (min-width:320px) { }
@media (min-width:480px) { }
@media (min-width:768px) { }
@media (min-width:960px) { }
@media (min-width:1200px) { }</p>
<p>Now if you're wanting to give older browsers (Internet Explorer 6/7/8) a single stylesheet that would give the 'desktop' design like Nicolas' post describes then you would have another LESS file called ie.LESS which would look like this -</p>
<p>/* ie.css */
@import 'default';
@import '320';
@import '480';
@import '768';
@import '960';</p>
<p>This again is pretty simple. Using the LESS.app it would put all of your sites styles in file called ie.css in the order of 'little to large' so that it would cascade to show your legacy browser that 'desktop' design.</p>
<p>As Nicolas points out at the bottom of his post, to include this into your HTML so that legacy IE browsers would use the ie.css you would put this in the <HEAD> of your markup -</p>
<p><!--[if (lt IE 9) & (!IEMobile)]>
    <link rel='stylesheet' href='/css/ie.css'>
    <![endif]--></p>
<h2 id="so%2C-what-now%3F" tabindex="-1">So, what now?</h2>
<p>Althought that currently does not work with LESS there are a couple of ways to get it to work.</p>
<p>If we keep the original style.LESS as this</p>
<p>/* styles.css */</p>
<p>@import 'default';
@media (min-width:320px) {
@import '320';
}
@media (min-width:480px) {</p>
<p>in the individual corresponding LESS file you would have for example this -</p>
<p>@media (min-width:320px) {
/* styles goes here */
}</p>
<p>Then when you save out your styles.LESS to CSS it will included all the CSS3 Media Queries with the styles within.</p>
<h2 id="that's-nasty!" tabindex="-1">That's Nasty!</h2>
<p>Yep, that's ok unless you wanted to save out a ie.css file too. Using the same approach of @import-ing the .LESS files and compiling them into a single ie.CSS file you would still get -</p>
<p>@media (min-width:320px) {
/* styles goes here */
}</p>
<p>That'd make your ie.CSS file pretty disgusting to look at and read through for yourself let alone anyone else looking at your code.</p>
<h2 id="well%2C-what-then%3F" tabindex="-1">Well, What then?</h2>
<p>There is a solution (of sorts) that would give you a styles.CSS file including all your CSS3 media queries and another stylesheet with the code in a cascading order without the media query syntax. It's a little bit more complex but once it's setup it can work in every site you create from then on.</p>
<p>First in your .LESS files that are specific to a break point in your responsive design, for example 768.LESS, include this code -</p>
<p>.max-width-768() {
/* style goes here */
}</p>
<p>Once you have populated your .LESS files with such code (for example files for 320, 480, 768, 960 and 1200 break points). You would then need to have your styles.LESS file looking like this -</p>
<p>/* styles.css */</p>
<p>@import '320.less';
@media (max-width: 320px) {
.max-width-320();
}
@import '480.less';
@media (max-width: 480px) {
.max-width-480();
}
@import '768.less';
@media (max-width: 768px) {
.max-width-768();
}
@import '960.less';
@media (max-width: 960px) {
.max-width-960();
}
@import '1200.less';
@media (max-width: 1200px) {
.max-width-1200();
}</p>
<p>Now you've done that you would want to create your single stylesheet for Internet Explorer. This is done as in the fictional bit of code at the top of the post. Like this -</p>
<p>/* ie.css */
@import 'default';
@import '320';
@import '480';
@import '768';
@import '960';</p>
<p>You'd then add this bit of code to so that it is picked up by older versions of Internet Explorer -</p>
<p><!--[if (lt IE 9) & (!IEMobile)]>
    <link rel='stylesheet' href='/css/ie.css'>
    <![endif]--></p>
<p>There we have it. A workable way of making  'Mobile First' CSS &amp; supporting older IE browsers using LESS.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Decisions, decisions, decisions</title>
      <link href="https://www.alwaystwisted.com/articles/decisions-decisions-decisions.html"/>
      <updated>2011-11-29T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/decisions-decisions-decisions.html</id>
      <content type="html">
        <![CDATA[
        <p>So, you're about to go live. You're just dotting that last lower case j on the site and you hit the 'go' button.</p>
<p>That new site you've been working on is live. It's out there on the information super highway. You're full of smiles. You think it looks great, you know it works fantastic and the cleanliness of your code is something to die for.</p>
<h3 id="but." tabindex="-1">But.</h3>
<p>You want to tell the world. Gone are the days of adding it to forums or even email people you know. Just one tweet and you can reach all your followers and more.</p>
<h3 id="what-next%3F" tabindex="-1">What Next?</h3>
<p>Everyone's seen your tweet and are looking at your site in their preferred browser. Then they start to resize the browser.</p>
<h3 id="'oh%2C-isn't-it-responsive%3F'" tabindex="-1">'Oh, isn't it responsive?'</h3>
<p>It may be, it may not be. It still a lovely design but with the poster child of design approachs being that fluid grid that'll resize to your mobile telephone's viewport most people expect it to resize.</p>
<p>If it doesn't a plethora of tweets as to the why and where fors abound. You're inundated.</p>
<h3 id="'why-do-i-have-to-explain-myself%3F'" tabindex="-1">'Why do I have to explain myself?'</h3>
<p>You don't. Plain and simple. But, I feel, that if you can you must write a little blog post explaining the business decision as to how you got to the site as it is live on the tubes.</p>
<h3 id="business-decisions" tabindex="-1">Business Decisions</h3>
<p>Time is money (or <a href="http://youtu.be/q8mgMXmsxlo">mime is money</a>). There are reasons that a site is how it is beyond how it looks. If we blog, just a little, on how we came to what we've done we would all get a better understanding of this forever growing industry and hopefully calm the 'But it's not…' tweets.</p>
<h3 id="it's-all-i-ask" tabindex="-1">It's all I ask</h3>
<p>So, next time you release that project you've been burning the midnight candle for. Just 'do' a quick blog post as to why, why and why.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>It Depends...</title>
      <link href="https://www.alwaystwisted.com/articles/it-depends.html"/>
      <updated>2011-11-13T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/it-depends.html</id>
      <content type="html">
        <![CDATA[
        <h2 id="an-introduction..." tabindex="-1">An Introduction...</h2>
<p>Since Ethan Marcotte's <a href="http://www.alistapart.com/articles/responsive-web-design/">seminal peice</a> on responsive web design we as an industry have really been talking/blogging about nothing else but.</p>
<p>That's a good thing. A great thing in fact. A majority of this industry have taken Ethan's idea for how to approach modern web design and ran with it. Some of us still don't think it's a 'trend' that'll catch on. Sure, like all things, in 5 years down the line we could be thinking 'why we're we wasting our time?'. I very much doubt that.</p>
<p>Another thought is that Responsive Web Design won't work for every project. This is true in part I feel.</p>
<p>Let's face it every project is different. Your next site build could be for the new restaurant that's opened up, a solo musicians blog or an online store selling every crayon imaginable. Could they all work with a responsive web designers approach? Probably but possibly not.</p>
<p>This is pretty much mentioned in Ethan's book. You've got that right? Read it yes? Good.</p>
<p>In the last chapter Ethan discusses the Johnny Ball (who, what, where, when, how?) of Responsive Web Design. In some cases RWD may not be the answer. I think regardless of that initial decision to use a responsive approach you should start out with at least part of the approach. Because. It may 'depend' now but down the timeline of the project something may change. If you start out with a fluid grid at least it'll help stop you having to shoehorn the techniques in at a later date. It's not much effort figuring out your pixels, your percentages and your ems and emlpoying them in your CSS.</p>
<p>If you think it is. Then you're just plain lazy.</p>
<p>Doing this at the start also allows you to 'turn it off'. You can set a media query in such a way that the site won't resize in the browser. It's a couple of lines. It's not much work.</p>
<p>If you think it is. Then you're just plain lazy.</p>
<h2 id="an-aside." tabindex="-1">An aside.</h2>
<p>Responsive Web Design is not the whole picture. It's only a part of the puzzle there's lots more 'stuff' to consider. Context, Content, Connection Speeds, Location. All of these things should be thought of with your design first.</p>
<p>This is why you shouldn't just be a web designer. You shouldn't just start being a Responsive web designer. You should start being a user centric, content first, context aware, mobile first, responsive web designer.</p>
<p>As ever, someone else has put this down in better words than I can muster. Check out @lukew's post on <a href="http://www.lukew.com/ff/entry.asp?1436">Multi-Device Web Design</a> for a more structure point of view.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>I am realigning, redesigning, changing &amp; growing</title>
      <link href="https://www.alwaystwisted.com/articles/i-am-realigning-redesigning-changing-growing.html"/>
      <updated>2011-07-21T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/i-am-realigning-redesigning-changing-growing.html</id>
      <content type="html">
        <![CDATA[
        <p>Just thought I'd throw a quick post up to let you all know (well all 3 of you) that I'm in the (lengthy) process of redesigning this site.</p>
<p>Of course, when I say redesign I mean realign. Well both actually. I created this rather hurridly over Christmas &amp; New Year 2010 and wanted to have so much 'fun' stuff on it I rushed it out the door before everything was ready (backstage area and the daily bit). So this time around I'm taking my time. I'm not rushing. If you know me, you know I never intentially rush (<a href="http://www.youtube.com/watch?v=HbR7axof1wk">'Life moves pretty fast. If you don't stop and look around once in a while, you could miss it.'</a>).</p>
<p>So what is going to happen?</p>
<p>Well I'm going to add an actual porftolio to the site (including my services) so that I can use this site to 'show off' (and hopefully get) client work. I did have a fantastic domain (<a href="http://www.handcodedmedia.com">www.handcodedmedia.com</a>) but as I'm struggling to have this the way I want it as a blog I think that trying to create an additional 'services' site would make <a href="http://en.wikipedia.org/wiki/All_work_and_no_play_makes_Jack_a_dull_boy">Jack a dull boy</a>.</p>
<p>I'm hoping to have a daily post. Just to spill some of the minutiae of my day with you all.</p>
<p>I'm hoping to create a 'labs' (previously underdeveloped backstage) area where I can just post quick ideas without the need for a full blog post.</p>
<p>I'll contiue writing this blog. Albeit more regularly. I'm also going to add the abilty to add comments to the blog (on my chosing). I did write previously that <a href="http://alwaystwisted.com/post.php?s=2011-02-24-why-have-i-not-got-comments-on">I don't want comments</a> but I feel that train of though was wrong. Not allowing people to comment on a post will invariably get them tweetin about their agreement or disagreement and thoughts which as we know is limited to 140 charecters and conversations get borken easily. So comments are good. Comments will be on :D</p>
<p>I'll add a portfolio, services and contact page. I'll 're-jig' the about page so it's less '<a href="http://www.thefreedictionary.com/wordy">wordy</a>' and that should pretty much be about it.</p>
<h2 id="responsive-web-designing" tabindex="-1">Responsive Web Designing</h2>
<p>If you do look at this on your 'mobile' device or tablet you'll see the responsive web design is a bit screwy. This was a slight afterthought and before mobile first went stellar. I have more users on iPads and iPhone than I do on IE6 + 7 combined.</p>
<p>My redesign will be built from the ground up. Using a bit of the <a href="http://html5boilerplate.com/">HTML5 Boilerplate</a>, a bit of the <a href="http://www.getskeleton.com/">Skeleton framework</a>, a bit of <a href="http://stuffandnonsense.co.uk/projects/320andup/">320 and up</a> so a bit of this that <a href="http://www.youtube.com/watch?v=tScm-eZInBE">and the other</a>.</p>
<p>I'm hoping to have this all done in time for the <a href="http://www.updateconf.com">UpdateConf</a> that I'm attending. Along with fresh business cards too :)</p>
<p>Until then, I may post. I may not. I had a great time watching some fantastic speakers at this years <a href="http://environmentsforhumans.com/2011/css-summit/">CSS Summit</a> and have several ideas and comments I want to share. So you never know. ;)</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>All of sudden I lost 14 inches</title>
      <link href="https://www.alwaystwisted.com/articles/all-of-sudden-i-lost-14-inches.html"/>
      <updated>2011-07-04T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/all-of-sudden-i-lost-14-inches.html</id>
      <content type="html">
        <![CDATA[
        <p>If you follow me on <a href="http://www.twitter.com/sturobson">twitter</a> and why wouldn't you? You may know that I've sold my 27' iMac. It took a while. I decided to sell it a little bit too late (just days after they updated the <a href="http://www.apple.com/thunderbolt/">whole range</a> again). So I was stuck with it on eBay for 30 days trying to sell it. Eventually I found a buyer. Or they found me.</p>
<p>One morning I woke to a message from <a href="http://message.uk.com/">Message</a> saying they're interesting in buying it from me. With a few quick tweets to them and various people asking for advice it wasn't long before the deal was struck.</p>
<p>A courier was to collect my iMac from me on Thursday and once delivered funds would be transferred into my account. That was a bit of a pain. I was worried that I'd be without a computer for the weekend. I panicked. After a couple more tweets to some fine fellows I decided to use my just cleared pay cheque to buy a MacBook Pro.</p>
<p>You may think I'm a bit mad. I've gone from a 27' massive <a href="http://www.apple.com/imac/">iMac</a> screen down to a 'tiny' 13' <a href="http://www.apple.com/macbookpro/">MacBook Pro</a>. Why? There's a couple of reasons.</p>
<ol>
<li>The iMac was a desktop. As I only use the computer in the evening as my web design shenanigans (for the moment) is purely 'part time'. I just couldn't get used to having to sit in the office (dining room). Whilst my partner was in the sitting room. I found myself using my iMac less and less.</li>
<li>27' is <a href="http://de.acidcow.com/pics/20100621/how_big_17.jpg">massive</a>. I found it was too big for me. I couldn't really concentrate as there were so many pixels to look at. The 13' is perfect. I've only got a small screen to look at. I can focus much better.</li>
</ol>
<p>So I got my MacBook Pro. A 13' 2011 model, 2.3Ghz i5 with 4GB of RAM and a 320GB 5200rpm hard drive. On the afternoon I ordered it <a href="http://www.twitter.com/lloydi">@lloydi</a> was talking about a hard drive he's got in his 15' 2008 MacBook Pro. A <a href="http://www.seagate.com/www/en-gb/products/laptops/laptop-hdd/">Seagate Momentus XT Hybrid</a>. It's got a 500GB 7200rpm hard drive AND a 4GB SSD in there too. The SSD basically helps your most used programmes open quicker. I was sold in seconds and ordered it after having the MacBook for only 4 days. It makes the laptop loads from cold quicker too. Whilst I was in a spending mood I also ordered 8GB of RAM too.</p>
<p>It all arrived, I installed it in moments (well, after a Time Machine backup).</p>
<p>It's one quick machine now.</p>
<p>I'm currently waiting 20 seconds when I boot up. Which is great. Photoshop, Coda, Chrome, Kiwi and Itunes load in a snap. No waiting. NONE.</p>
<p>Total cost for the upgrade £150 (ish). The MacBook Pro, being a refurb model, was £849 instead of the usual £999 rrp. A grand well spent.</p>
<p>I think this'll last me for some years to come. I can't see me every going back to a desktop. Well, Never say never.</p>
<p>But there must be some problems right?</p>
<p>Yes, of course. I've been 'used to' my iMac with a magic mouse and a wireless keyboard. All of a sudden I have to use a trackpad. My <a href="http://en.wikipedia.org/wiki/Muscle_memory">muscle memory</a> needed 'retraining' but that's done now.  The other thing is the screen (under certain circumstances). It's a glossy screen. So depending where I'm sitting in the house. I sometimes don't get the best view of the screen because of all of the glare and reflections. But that's ok. I can sit in another chair.</p>
<p>And that's about it. I've got a new toy. I'm 'blogging' again. I'm trying to do some more work. I've got several projects 'on the go' so being able to use this bad boy wherever I am makes it easier than it ever used to be.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Last Weeks Hot Topics (03/07/11)</title>
      <link href="https://www.alwaystwisted.com/articles/last-weeks-hot-topics-030711.html"/>
      <updated>2011-07-03T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/last-weeks-hot-topics-030711.html</id>
      <content type="html">
        <![CDATA[
        <p>Here's a quick selection from this weeks blog posts I've found interesting from my RSS feed.</p>
<p>I hope you do too.</p>
<p>So, sit back, Relax!. Have a cup of Joe.</p>
<p>Enjoy.</p>
<p>If you've got any suggestions or you've got a blog I should add to my list of many then catch me on <a href="http://www.twitter.com/sturobson">twitter</a></p>
<p><a href="http://feedproxy.google.com/~r/veerlesblog/~3/ZI64WcuxHjs/">CSS3 Linear Gradients</a><br>
Good write-up on CSS3 Linear Gradients + link to useful tool....=</p>
<p><a href="http://tympanus.net/codrops/2011/07/03/sliding-background-image-menu/">Sliding Background Image Menu with jQuery</a><br>
View demo Download source Today we want to share another jQuery menu with you. This menu will have several panels, each one corresponding to a different background image that will show on all panels w...</p>
<p><a href="http://www.webresourcesdepot.com/leanmodal-a-micro-jquery-modal-plugin/">leanModal – A Micro jQuery Modal Plugin</a><br>
Advertise here with BSA leanModal is a lightweight jQuery plugin for displaying modal boxes with minimum effort. The plugin doesnt use any images and a very good solution for for displaying anything...</p>
<p><a href="http://giraffeforum.com/wordpress/2011/07/03/eliminate-task-duplicates/">Eliminate task duplicates</a><br>
How many unique tasks are there in the following list? • Book an appointment online • Appointment reminders • Let me book an appointment • Make an appointment • Request an appointment Yes, two. One ta...</p>
<p><a href="http://feedproxy.google.com/~r/ProbloggerHelpingBloggersEarnMoney/~3/O112kYlFn2I/">Are You a Creative Blogger?</a><br>
This guest post is by Chris Kahler of <a href="http://bloggeritus.com/">bloggeritus.com</a> . It doesn’t take a genius to stroll around cyberspace and quickly find that the World Wide Web is littered with junk. There is a lot of “stuff” ...</p>
<p><a href="http://feedproxy.google.com/~r/CreativeDesign/~3/wKD1LangDSU/">Aesop on giving critiques</a><br>
It’s easy to speak negatively about the work of others, but never forget the quality of your own. The Two Bags According to ancient lore, every man is born into the world with two bags suspended from ...</p>
<p><a href="http://www.readactor.com/premium-wordpress-theme/rockwell-portfolio-blog-wordpress-theme/">RockWell – Portfolio &amp; Blog WordPress Theme</a><br>
Click on image for demo! Features 43 Unique ‘Category’ Templates – could be used as a Blog, Portfolio or just about anything you want 20 Unique ‘Single Post’ Templates – could be used as a Blog, Portf...</p>
<p><a href="http://feedproxy.google.com/~r/tripwiremagazine/~3/_NlqLhVWJSk/beautiful-yellow-website-designs.html">40 Examples of Beautiful Yellow Website Designs</a><br>
Yellow is the color evoked by light that stimulates both the long and medium wavelength cone cells of the retina about equally, with no significant stimulation of the short-wave cone cells . A Light w...</p>
<p><a href="http://rel.ly/2011/07/01/wavingnotdrowning/">Waving not drowning: or how I gave in and learned to love the content strategy flood.</a><br>
Here’s a sobering admission. If the body of knowledge of content strategy is an ocean, I’m currently about ten foot out from</p>
<p><a href="http://feedproxy.google.com/~r/LostAndTaken/~3/ZhKjGBaq9sY/19-free-block-print-textures.html">19 Free Block Print Textures</a><br>
I've got a cool treat for you guys today. L&amp;T reader Derek Oscarson has provided this set of 19 free letterpress and block print textures that you can use freely in your design projects (personal &amp;co...</p>
<p><a href="http://freelancefolder.com/50-questions-to-ask-yourself-after-6-months-of-freelancing/">50 Questions to Ask Yourself after 6 Months of Freelancing</a><br>
tweetmeme_source = 'FreelanceFolder'; It’s a well-known fact that most freelancers don’t get performance reviews. For one thing, most private clients don’t think of it. Even on bidding sites where...</p>
<p><a href="http://feedproxy.google.com/~r/gavinelliottblog/~3/BJNdNZJqA84/">The healthy future of the web industry maybe short-lived</a><br>
Just three weeks ago I was stood on a stage in Vancouver, Canada. One of the first lines I said to the audience was, “Our industry is in one of the most exciting times of its life.”I meant every singl...</p>
<p><a href="http://feedproxy.google.com/~r/Webappers/~3/euLZtj-bc-g/">CSS3 Transitions with Custom Easing Functions</a><br>
CSS3 transitions are easy to implement, more performant than the setTimeout based alternative &amp;because of this work really well on mobile devices. However, it is not as flexible as the Javascript alte...</p>
<p><a href="http://acrisdesign.com/2011/06/fabric-texture-in-web-design/">Fabric Texture In Web Design</a><br>
In this showcase we have featured some of beautiful and creative fabric textured web designs for inspiration which inspired you how to use a fabric textures in your own web design. We also included so...</p>
<p><a href="http:/?p=5261#comments">Add a Google+ Badge to Your Website</a><br>
Google’s new Google+ service is taking the development world by storm, and why shouldn’t it?  It’s minimalistic UI, use of cutting edge web techniques, and overall usability make it Google+ one of the...</p>
<p><a href="http://www.crazyleafdesign.com/blog/10-principles-of-effective-web-designing/">10 Principles Of Effective Web Designing</a><br>
Web designing is not just creating a site with colorful images. You need to follow various rules and use tools for designing a website to attract target traffic. Using website design templates has si...</p>
<p><a href="http://freelancefolder.com/7-top-freelance-survival-tips/">7 Top Freelance Survival Tips</a><br>
tweetmeme_source = 'FreelanceFolder'; These seven freelance survival tips will help to see you through the lean times -and there will be lean times, at least until you have an established, reliabl...</p>
<p><a href="http://feedproxy.google.com/~r/SixRevisions/~3/kgMVOgGzfqQ/">Things Worth Paying For as a Freelancer</a><br>
Advertise here with BSA A freelancer, like a baker, needs a few essential tools with which they create their products and use in order to offer their services. Instead of pots, mixing bowls, spoons an...</p>
<p><a href="http://www.webdesignerdepot.com/2011/06/ribbons-and-tags-in-web-design/">Ribbons and tags in web design</a><br>
Trends can be born so silently and subtly that we seldom notice them. And when you survey hundreds of websites, you often see patterns that you would otherwise miss. One such pattern is the frequent u...</p>
<p><a href="http://www.1stwebdesigner.com/design/creating-faq-tips/">5 Simple Tips for Creating an Effective FAQ Page</a><br>
A Frequently Asked Questions page is necessary if you’re selling something, providing a service, or giving information about a complex subject. It takes the guesswork away from your visitors who may h...</p>
<p><a href="http://feedproxy.google.com/~r/vitaminmasterfeed/~3/sam1EZB9iRw/">Episode #28: News Roundup and Ryan’s Weird Thing of the Week</a><br>
This week Ryan is back from his spreadsheets and talks us through the possibilities of 3D hologram websites. We also discuss using WordPress to power your newspaper , the release of GitHub for Mac ,...</p>
<p><a href="http://feedproxy.google.com/~r/webexpedition18com/~3/PHlVF5Crdxc/">You Want To Become An Effective Web Designer? Follow These Steps!</a><br>
Tweet Web designing is not just creating a site with colorful images. You need to follow various rules and use tools for designing a website to attract target traffic. Using free web site templates ha...</p>
<p><a href="http://webdesignledger.com/inspiration/typography-inspiration-20-creative-examples">Typography Inspiration: 20 Creative Examples</a><br>
Advertise here with BSA The word typography , from the greek word typos, is the art and technique of arranging type. And I have to agree that arranging typography is an art. Some designers have the r...</p>
<p><a href="http://lazyload-plugin/#comments">Introducing LazyLoad 2.0</a><br>
While improvements in browsers means more cool APIs for us to play with, it also means we need to maintain existing code.  With Firefox 4#8242s release came news that my MooTools LazyLoad plugin was ...</p>
<p><a href="http://blog.typekit.com/2011/06/29/using-typekit-fonts-in-your-own-css/">Using Typekit fonts in your own CSS</a><br>
With some of the recent improvements to our kits , Typekit is providing more tools for using fonts on the web than ever before. The options range from basic and drop-dead simple (just add fonts and s...</p>
<p><a href="http://feedproxy.google.com/~r/nettuts/~3/qmQB6KV-cDA/">Showcase of Inspiring “About Me” Pages</a><br>
Advertise here A creative about me page will attract a reader’s attention, and, more importantly, provide them with a quick sampling of what you or your company represents. Are you playful, stylish, c...</p>
<p><a href="http://feedproxy.google.com/~r/GraphicDesignBlender/~3/1DWBxDhe-EM/charge-for-your-design-time">Charging for freelance design: by the hour or per project?</a><br>
Have you ever found yourself pulling your hair out over how much to charge for a design project? It can be very frustrating and usually ends up costing you more time (and thus money) than it should. T...</p>
<p><a href="http://feeds.copyblogger.com/~r/Copyblogger/~3/7BxnSD6cwnU/">When You Absolutely, Positively Must Know if Your Content Will Rock … Do This</a><br>
Ever had a great idea, and then started to doubt yourself? Or maybe you’ve already executed on that great idea, but you’re hesitating to launch. Maybe it’s an article, or an ebook, or a completely new...</p>
<p><a href="http://www.smashingmagazine.com/2011/06/29/five-copywriting-errors-that-can-ruin-a-company-website/#comments">Five Copywriting Errors That Can Ruin A Company’s Website</a><br>
No matter how brilliant a website’s design, no matter how elegant its navigation, sooner or later visitors will decide whether to take action because of something they read . In the end, the effectiv...</p>
<p><a href="http://www.attitudedesign.co.uk/attitude-design-official-apple-iphone-app-developers/">Attitude Design Official Apple iPhone App Developers</a><br>
We’re pleased to announce that Attitude Design are now official Apple Developers. This means we can now create Apps officially under the name of Attitude Design Ltd. We have been developing apps for t...</p>
<p><a href="http://feedproxy.google.com/~r/creativeoverflowblog/~3/5w_01LlunXg/">The Mysterious Ways of Web Typography</a><br>
It has recently come to my attention that there are more honest politicians than there are web designers who understand typography. As few as that!? You cry. When I say ‘typography’here, I am not tal...</p>
<p><a href="http://feedproxy.google.com/~r/speckboy-design-magazine/~3/fF5QygpdaiU/">How to Create a Basic WordPress Theme with Gantry Framework</a><br>
Advertise here with BSA Gantry Framework is a WordPress theme framework that, unlike most of its modern counterparts, allows the user to construct a layout and color palette from within the WordPress ...</p>
<p><a href="http://feedproxy.google.com/~r/Webappers/~3/vQ2ek23yPiQ/">Share Your Code with GitHub for Mac</a><br>
GitHub for Mac has just launched recently. Now you can Clone repositories, Browse history, Commit changes, Branch code, and Share code on <a href="http://github.com/">github.com</a> as simple as possible. The sync button pushes your ...</p>
<p><a href="http://www.visualswirl.com/inspiration/best-law-firm-website-designs/">25 of the Best Law Firm Website Designs</a><br>
Attorney websites have a history of being boring and bland. Pages and pages of legal history and attorney-speak can only be spiffed up so much, right? Well it looks like some lawyers have started taki...</p>
<p><a href="http://csswizardry.com/2011/06/fluid-grid-calculator/">Fluid grid calculator</a><br>
What with Ethan’s book and A List Apart article the whole community is responsive design mad. Which is a good thing…I’ve been looking at redesigning CSS Wizardry onto a fluid grid and also adding a ...</p>
<p><a href="http://css-tricks.com/9838-techniques-for-context-specific-images/">Techniques for Context Specific Images</a><br>
One of the shortfalls of using CSS media queries as the only ingredient of a mobile solution is that the same content gets served to both desktop browsers and mobile devices (which theoretically are s...</p>
<p><a href="http://feedproxy.google.com/~r/artatm/~3/elIXLtnDDBU/">How should a web designer use the services of social media?</a><br>
Social media is the hottest topic online, but recently its importance seems to be transcending to real life as well. The great advantage of social media is that it allows people to communicate and exc...</p>
<p><a href="http://vandelaydesign.com/blog/galleries/navigation-menus/">25 Beautiful Navigation Menus</a><br>
Navigation menus are a critical part of web design because of their importance for usability and creating a position user experience. Websites with poor navigational structure or a lack of clarity in ...</p>
<p><a href="http://www.1stwebdesigner.com/css/css-counters-organize-ordered-content/">CSS Counters – The Right Way to Organize Your Ordered Content</a><br>
It is pretty common to see step-based content. Tutorials, shopping carts, FAQ’s, grandma’s recipes. You know, numbers and steps are really good to grab attention, so many writers use this....</p>
<p><a href="http://www.noupe.com/design/the-keys-to-making-fresh-forwardly-aesthetic-web-designs.html">The Keys to Making Fresh, Forwardly Aesthetic Web Designs</a><br>
Great graphics . Beautiful typography . Clean design . These are all things designers typically think of when creating stunning websites. But is it really just that combination of elements that pro...</p>
<p><a href="http://www.virtuosimedia.com/business/marketing/how-to-plan-content-marketing-strategies-for-your-website">How To Plan Content Marketing Strategies For Your Website</a><br>
Theres an old saying that goes “If you fail to plan, youre planning to fail.”To put that another way, no one ever plans to fail or do a bad job, but plenty of people plan to make a plan of any kind...</p>
<p><a href="http://feedproxy.google.com/~r/tripwiremagazine/~3/pmx3xj4wVE8/25-informative-yql-tutorials-to-get-you-started-with-yql.html">25 Informative YQL tutorials to get you started with YQL</a><br>
Yahoo! query language ( YQL ) is an SQL-like query language created by Yahoo! as part of their Developer Network. YQL is designed to retrieve and manipulate data from APIs through a single Web interfa...</p>
<p><a href="http://feedproxy.google.com/~r/TheSocialMediaChannel/~3/15x6Pndetl4/">9 ways to build an easy, engaging content strategy</a><br>
Technology and luxury: two industries that move at a fast pace, demanding constant innovation and high quality products. Luxury was slow in embracing the digital world, but has come a long way in a so...</p>
<p><a href="http://spyrestudios.com/30-creative-navigation-menus/">30 Creative Navigation Menus</a><br>
It’s not always easy creating a navigation menu that stands out, and also serves its purpose without getting in the way. Sites that have a huge number of category pages in particular can be quite daun...</p>
<p><a href="http://www.smashingmagazine.com/2011/06/27/useful-ideas-and-guidelines-for-good-web-form-design/#comments">Useful Ideas And Guidelines For Good Web Form Design</a><br>
The input form is an essential element of almost any website or application these days. Input is a core method of interaction, and in many cases it represents the hard conversion point between success...</p>
<p><a href="http://feedproxy.google.com/~r/SmashingApps/~3/cZheUyJwIM4/50-minimalist-and-stylish-free-wordpress-themes.html">50 Minimalist And Stylish Free WordPress Themes</a><br>
WordPress is the preferred content management system of many bloggers and internet marketers owing to many reasons. Out of them its easily available theme is the most important reason that can complet...</p>
<p><a href="http://feedproxy.google.com/~r/creativeoverflowblog/~3/fIShLlAqJCU/">Should Freelance Designers Run Design Blogs?</a><br>
To blog or not to blog -that is the question. For freelancers, especially designers, it can be a particularly difficult question. Blogs have popped up as one of the most recommended methods for a free...</p>
<p><a href="http://www.1stwebdesigner.com/css/object-oriented-css/">An Introduction to Object Oriented CSS</a><br>
With richer interactions and media heavy pages mushrooming on the web, creating web pages, which load faster and respond well has become a challenge. Separating the content, presentation and behavior ...</p>
<p><a href="http://speckyboy.com/2011/06/26/html5-and-css3-form-references-resources-and-tutorials/">HTML5 and CSS3 Form References, Resources and Tutorials</a><br>
Advertise here with BSA This article explores some of the new HTML5 form features and how it has greatly improved text inputs, search boxes and other form fields by providing better and cleaner contro...</p>
<p><a href="http://feedproxy.google.com/~r/Line25/~3/SRQeshFDYkw/showcase-of-impressive-design-process-explanations">Showcase of Impressive Design Process Explanations</a><br>
A common feature amongst the top design portfolio and agency websites is a visually presented explanation of their design process. This simple idea of describing how a potential client’s project will ...</p>
<p><a href="http://webdesignledger.com/inspiration/25-examples-of-capital-letters-usage-in-web-design">25 Examples of Capital Letters Usage in Web Design</a><br>
Advertise here with BSA Letter case -in orthography and typography is the distinction between the larger majuscule (capital, caps, upper-case, upper case, or uppercase) and smaller minuscule (lower-ca...</p>
<p><a href="http://feedproxy.google.com/~r/smileycat/~3/dNZD0pO_2ps/002564.php">8 Reasons Why Bad Web Design Decisions Get Made</a><br>
Sometimes when I'm struggling to complete a task on a website (or am watching my wife throw her arms up in frustration), I ask myself 'What genius decided to build it like that?' Having been on the ot...</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Last Weeks Hot Topics (26/06/11)</title>
      <link href="https://www.alwaystwisted.com/articles/last-weeks-hot-topics-260611.html"/>
      <updated>2011-06-26T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/last-weeks-hot-topics-260611.html</id>
      <content type="html">
        <![CDATA[
        <p>Here's a quick selection from this weeks blog posts I've found interesting from my RSS feed.</p>
<p>I hope you do too.</p>
<p>So, sit back, Relax!. Have a cup of Joe.</p>
<p>Enjoy.</p>
<p>If you've got any suggestions or you've got a blog I should add to my list of many then catch me on <a href="http://www.twitter.com/sturobson">twitter</a></p>
<h2 id="tutorials%2C-tricks-%26-plugins" tabindex="-1">Tutorials, Tricks &amp; Plugins</h2>
<p><a href="http://www.css-tricks.com/9876-learn-canvas-snake-game/">Learning Canvas: Making A Snake Game</a> from CSS-Tricks</p>
<p><a href="http://www.webresourcesdepot.com/lightweight-jquery-plugin-for-overlays-simple-overlay/">A jQuery plugin for Overlays</a> from Web Resources Depot</p>
<p><a href="http://www.onextrapixel.com/2011/06/20/creating-depth-in-web-design-5-design-tricks/?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed%3A+onextrapixel+%28Onextrapixel%29">Creating Depth in Web Design: 5 Design Tricks</a> from One Extra Pixel</p>
<p><a href="http://www.tripwiremagazine.com/2011/06/showcase-and-tips-how-to-create-effective-landing-page-designs.html?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed%3A+tripwiremagazine+%28tripwire+magazine%29">How To Create Effective Landing Page Design</a> from Tripwire Magazine</p>
<h2 id="round-ups%2C-best-ofs-%26-compilations" tabindex="-1">Round-Ups, Best-Ofs &amp; Compilations</h2>
<p><a href="http://www.smashingapps.com/2011/06/23/50-creatively-designed-unusual-and-entertaining-404-error-pages-worth-checking-out.html?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed%3A+SmashingApps+%28Smashing+Apps%29">50 Creatively Designed 404 Error Pages</a> from Smashing Apps</p>
<p><a href="http://www.youthedesigner.com/2011/06/23/51-high-quality-free-texture-packs-to-download/">51 Hi Quality Textures Packs</a> from You The Designer</p>
<p><a href="http://vandelaydesign.com/blog/design/free-photoshop-patterns/">UltimateRound Up of Free Photoshop Patterns</a> from Vandelay Design</p>
<p><a href="http://psd.fanextra.com/articles/the-best-free-sans-serif-fonts-for-designers/">The Best Free Sans-Serif Fonts</a> from PSDFAN EXTRA</p>
<h2 id="inspiration%2C-thought-provoking-%26-opinion-pieces" tabindex="-1">Inspiration, Thought Provoking &amp; Opinion Pieces</h2>
<p><a href="http://www.smashingmagazine.com/2011/06/22/following-a-web-design-process/#comments">Following A Web Design Process</a> from Smashing Magazine</p>
<p><a href="http://www.webdesignerdepot.com/2011/06/how-to-avoid-a-redesign-failure/">How To Avoid A Redesign Failure</a> from Webdesigner Depot</p>
<p><a href="http://graphicdesignblender.com/design-portfolio-attracting-clients">Ensure Your Design Portfolio Is Attracting Client</a> from Graphic Design Blender</p>
<p><a href="http://www.cennydd.co.uk/2011/why-personas-should-use-real-photos/?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed%3A+cennydd+%28Ineffable++%2F++Cennydd+Bowles%29">Why Personas Should Use Real Photos</a> from Cennydd Bowles</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>A Spaces Cowboy</title>
      <link href="https://www.alwaystwisted.com/articles/a-spaces-cowboy.html"/>
      <updated>2011-06-24T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/a-spaces-cowboy.html</id>
      <content type="html">
        <![CDATA[
        <p>As I've mentioned, I've got rid of my 27' iMac and have shrunk my 'screen real estate' down to a 13' MacBook Pro. I've had it a little over a week now. I've upgraded bits of it already (I'm gonna post about that) But it wasn't until <a href="http://www.twitter.com/sazzy">@sazzy</a> tweeted this morning that she's just <a href="http://twitter.com/sazzy/status/84227428129583104">'discovered Spaces on OS X'</a>.</p>
<p>Until that tweet, for some reason, I'd completely forgotten about <a href="http://www.apple.com/macbookpro/software.html#gallery-macosx-spaces">Spaces</a>. I've spent that last week having my twitter client, browser, photoshop, coda and anything else I open in the same 'window space'.</p>
<p>It's awesome.</p>
<p>I now have my email and twitter client in one space, coda in another, photoshop another, everything else in 'space number one'.</p>
<p>You should, if you haven't already, really check it out. With keyboard shortcuts it makes switching so frickin' easy.</p>
<p>Me LOVES IT!</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Last Weeks Hot Topics (19/06/11)</title>
      <link href="https://www.alwaystwisted.com/articles/last-weeks-hot-topics-190611.html"/>
      <updated>2011-06-19T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/last-weeks-hot-topics-190611.html</id>
      <content type="html">
        <![CDATA[
        <p>Hey,</p>
<p>I read a lot of blogs, my RSS list is humongous . I've been meaning to start a post like this for ages. For the moment (well hopefully just this week) it's going to just be a list. In the future (well hopefully next week) it will become a bit more 'finished'.</p>
<p>How do I do it? Quite easily. I've solely use NewsRack on my iPhone for reading my RSS. When I find something I thinks of interest when reading through the posts I mark it as new again. Then I'll send that list in an email to myself which in turn gets put into this post.</p>
<p>So, sit back, Relax!, Have a cup of Joe.</p>
<p>Enjoy.</p>
<p>(If you've got any suggestions or perhaps you've got a blog post I should add to my list then catch me on twitter - <a href="http://twitter.com/sturobson">@sturobson</a></p>
<p><a href="http://www.webresourcesdepot.com/free-wordpress-e-commerce-plugin-jigoshop/">Free WordPress E-Commerce Plugin – Jigoshop</a></p>
<p><a href="http://feedproxy.google.com/~r/ProbloggerHelpingBloggersEarnMoney/~3/ZA46iT0rX88/">Optimize the Most Underutilized Page of Your Blog</a></p>
<p><a href="http://csswizardry.com/2011/06/what-is-inuit-css/">What is inuit.css?</a></p>
<p><a href="http://feedproxy.google.com/~r/productivedreams/~3/y5e6EtxND3Y/">12 Steps to better navigation</a></p>
<p><a href="http://feedproxy.google.com/~r/savedelete/~3/KnG5-ukOG88/creating-a-impressive-headlinetagline-and-10-great-examples.html">Creating a Impressive Headline / Tagline &amp; 10 Great Examples</a></p>
<p><a href="http://css-tricks.com/2011/06/screen-resolution-notequalto-browser-window-9778">Screen Resolution ≠ Browser Window</a></p>
<p><a href="http://feedproxy.google.com/~r/SmashingApps/~3/X51n-bZyeXo/50-useful-and-free-html-newsletter-templates.html">50 Useful And Free HTML Newsletter Templates</a></p>
<p><a href="http://acrisdesign.com/2011/06/ultimate-collection-of-free-photoshop-pattern/">Ultimate Collection Of Free Photoshop Pattern</a></p>
<p><a href="http://www.robbiemanson.com/articles/a-new-approach-part-i/">A New Approach (Part I)</a></p>
<p><a href="http://feedproxy.google.com/~r/FreelanceSwitch/~3/FGPsxQo_4sk/">Ask FreelanceSwitch: Portfolios and Blog Content</a></p>
<p><a href="http://www.1stwebdesigner.com/design/stay-organized-and-stay-ahead-of-your-competition/">Stay Organized and Stay Ahead of Your Competition</a></p>
<p><a href="http://feedproxy.google.com/~r/artatm/~3/xjIBuT6kKvI/">50 Beautifully Designed Single Page Websites</a></p>
<p><a href="http://feedproxy.google.com/~r/speckboy-design-magazine/~3/U3PpynKA_Fw/">Home Office Tips – Eliminating Distractions When Working From Home</a></p>
<p><a href="http://feedproxy.google.com/~r/tripwiremagazine/~3/4rKVXjZ1Vyo/what-theme-options-does-your-wordpress-theme-need.html">What theme options does your WordPress theme need?</a></p>
<p><a href="http://www.webdesignerdepot.com/2011/06/why-typography-rules/">Why typography is the Web’s greatest media format</a></p>
<p><a href="http://www.1stwebdesigner.com/design/web-typography-guide/">A Simple Guide to Improving Web Typography</a></p>
<p><a href="http://feedproxy.google.com/~r/VigetInspire/~3/M_UbBkTfIZ4/">In Defense of the Humble, Often Overlooked Contact Page</a></p>
<p><a href="http://www.crazyleafdesign.com/blog/free-social-icons/">Picons Social Pack, Free High Quality Social Icons</a></p>
<p><a href="http://spyrestudios.com/750-free-photoshop-brushes-to-download/">750+ Free Photoshop Brushes to Download</a></p>
<p><a href="http://feedproxy.google.com/~r/vectortuts/~3/1IbUjx_bR_A/">How to Make a Happy and Safe Office Space</a></p>
<p><a href="http://webdesignledger.com/tips/strategies-for-task-management-working-with-clients">Strategies for Task Management Working with Clients</a></p>
<p><a href="http://www.1stwebdesigner.com/design/how-to-improve-web-designer/">9 Tips on How To Improve Yourself as a Web Designer</a></p>
<p><a href="http://feedproxy.google.com/~r/WebDesignerNotebook/~3/lyIw9KBZfXQ/">The Wonderful calc() Function</a></p>
<p><a href="http://acrisdesign.com/2011/06/responsive-web-design-examples-and-tutorials/">Responsive Web Design: Examples And Tutorials</a></p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Time for a change...</title>
      <link href="https://www.alwaystwisted.com/articles/time-for-a-change.html"/>
      <updated>2011-06-18T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/time-for-a-change.html</id>
      <content type="html">
        <![CDATA[
        <p>I've sold my iMac. Finally. I knew I should have attempted to sell it before the new range of iMacs were released. But no, I waited. I'm really happy it's gone though. It's gone to a great company down in Brighton. A company that I would love to work for in fact. So at least part of me is now by the seaside.</p>
<p>So what have I done with my spoils? I managed to get a healthy £1000 for my iMac which included a magic trackpad and remote control. So with that I have purchased, and am using now, a 2011 13' MacBook Pro. It's the low end model available for £999 from Apple. Mine's a refurbished model so I got it for £849 instead. So far I've not notice any difference in what I'd expect from a 'brand new' MacBook. Except for the boring plain white packaging.</p>
<p>It's quite a jump. It really is. For 18 months or so I've had the luxury of 27' of Apple LED display in the iMac and now I've got a 'tiny' 13 inches. But it's fine. That's where the multi finger gestures on the track pad come in really handy. That's the other thing I'm trying to get used to after using a fat old magic mouse for a year and half I've got to get used the the fact it's my fingers and not my hand that has got to move the cursor around the screen now. But, I'm getting used to it.</p>
<p>So what now? Well. Now that I can literally sit anywhere and work I'm hoping this will up my productivity in the evenings when I mainly freelance. Just by reading this you can see I'm 'blogging' again.</p>
<p>What's in the pipeline? I've got several client projects 'on the go' so I'm hoping to finish these ASAP and then get my 'freelancer for hire' site un and running.</p>
<p>So plenty to do AND I hope to blog more. Fingers crossed.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Ideas Of March</title>
      <link href="https://www.alwaystwisted.com/articles/ideas-of-march.html"/>
      <updated>2011-03-15T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/ideas-of-march.html</id>
      <content type="html">
        <![CDATA[
        <p>Whilst at 'the day job' this morning I checked twitter to see that <a href="http://www.twitter.com/MrQwest">@MrQwest</a> had tweeted a blog post entitled <a href="http://mrqwest.co.uk/blog/148/ideas-of-march-ideasofmarch">'Ideas if March'</a>. Having seen his previous tweets about having a load of blog ideas I though this would be a brief list of said ideas. I was wrong. In fact Anthony's blog post took me to <a href="http://shiflett.org/blog/2011/mar/ideas-of-march">a post</a> written by <a href="http://www.twitter.com/Shiflett">Chris Shiflett</a>.</p>
<p>I love twitter as a platform for chatting, asking and answering questions but sometimes what is being said has to be truncated to fit into the 140 charecters. As such conversations can become disjointed and you may find yourself including someone who left the chat a while back.</p>
<p>I've only recently started blogging. I've been 'designing websites' since the early days. I can remember the joy when I could use a:hover. I even found an old site the other day that was 'best viewed' in IE 4+ and NN 4+ but, I've only just started blogging.</p>
<p>Part of the reason is because I like the idea of sharing what techniques I find/create using the new CSS3 properties but I've found that it's a good outlet for a <a href="http://alwaystwisted.com/post.php?s=2011-02-20-dont-let-your-menu-take-over">bit of a rant</a> that I can't quite fit into 140 charecters.</p>
<p>Before I digress anymore let's get on with it. In Chris's post he outlined several things he'd like us to do in our Ideas of March post.</p>
<ul>
<li>Write a post called Ideas of March</li>
<li>List some of the reasons you like blogs.</li>
<li>Pledge to blog more the rest of the month.</li>
<li>Share your thoughts on Twitter with the <a href="http://search.twitter.com/search?q=%23ideasofmarch">#ideasofmarch</a> hashtag.</li>
</ul>
<h3 id="why-i-like-blogs" tabindex="-1">Why I Like Blogs</h3>
<ul>
<li>There's room to breath outside of 140 charecters.</li>
<li>You can keep the context of your topic of discussion.</li>
<li>You can evolve your initial ideas and talk more in depth about the chosen subject.</li>
<li>Each posts helps the next.</li>
</ul>
<h3 id="why-i-don't-like-blogs" tabindex="-1">Why I Don't Like Blogs</h3>
<p>There is always a but.</p>
<ul>
<li>Comments, I'd much rather you say what you think in your own post. Rather than rush it in a blog comment or even a tweet.</li>
</ul>
<h3 id="in-the-end" tabindex="-1">In The End</h3>
<p>I've never really fallen out with blogs, my RSS feed shows me that. But I feel that we do need a revival. If you blog about what you're thinking it's better documented than in a barrage of tweets. If you don't agree with something, write it down in long form. If you do agree with something, write it down in long form. If you have an idea, write it down in long form. To help us all make sense of this infant technology write it down in long form so that we can all shape it to be the best is can be.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Geek Ninja Battle Night - a review of sorts</title>
      <link href="https://www.alwaystwisted.com/articles/geek-ninja-battle-night-a-review-of-sorts.html"/>
      <updated>2011-03-12T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/geek-ninja-battle-night-a-review-of-sorts.html</id>
      <content type="html">
        <![CDATA[
        <p><img src="/images/articles/geek-ninja-battle-night-image.jpeg" alt="geek ninja battle night image" loading="lazy" decoding="async"></p>
<p>Yesterday I ventured from the cosiness of my West Country Mansion to drive the motorways and A roads of Blighty to the seaside town of Brighton. Attending <a href="http://geekninjafactory.com/geek-ninja-battle-night-mobile-web-vs-native">The Geek Ninja Battle Night</a> that was being run by <a href="http://www.twitter.com/aral">Aral Balkan</a> which included himself as one of the 4 speakers with <a href="http://www.twitter.com/sazzy">Sarah Parmenter</a>, <a href="http://www.alwaystwisted.com/blog/www.twitter.com/rem">Remy Sharp</a> and <a href="http://www.alwaystwisted.com/www.twitter.com/Malarkey">Andy Clarke</a>.</p>
<p>It was a novel (an amazingly brilliant) idea to give an evening event a discussion topic and having the two 'sides' set to 'battle' over which 'side' is best at the task in hand. For this event (hopefully the first of many) the subject matter was designing and developping for mobile. There were two teams, Team Web (blue) who were represented by Andy and Remy pitted against Team Native (red) who were aptly represented by Sarah and Aral.</p>
<p>I did take <a href="http://instagr.am/p/CLN__/">some notes</a> but they were few and far between as I spent most of the time just soaking up the presentations like a sponge.</p>
<p>Because of this I can only discuss what I took away from the evening. Anything more and I wouldn't be sure if I dreamt bits of it or not. This 'idea' came to me as Aral was gesticulating at the front of the room with so much passion and energy.</p>
<p>Here goes...</p>
<p>We shouldn't be worrying about how we design for the devices that access the internet and what is the best technology to use first. We should be thinking first and foremost about the content and the context in which that content will be used, irregardless of it being within a native app or a 'web app' (sorry Andy).</p>
<p>What matters is when I'm 'in town' and I fancy a pizza for a spot of lunch I can get out my smartphone, open the browser, go to the pizza express web site which takes me to what I need to know. I want to know where the nearest chain is, I'm not bothered by company literature, big images. I want to find the nearest chain, get a telephone number and make a reservation.</p>
<p>Of course, this could all be done using the specific os's native coding. But what I'm getting at, and I'm probably labouring (not laboring) the point, is that it's the content I required for the context I was in.</p>
<p>You're on a mobile phone. You don't neccesarily want to read a ton of stuff. You are going to be very task orientated.</p>
<p>The only thing I would emplore you to do in which ever way you develop for mobile when choosing native or web is <strong>always</strong> include a link to the full site.</p>
<p>I only managed a quick thank you to Aral at the end and didn't get to say hi to Sarah, Andy (we've chatted about books &amp; amazon on the phone) or Rem. But thank you all. It was a great evening, I hope, had by all.</p>
<p>nb. the image above has been taken from Aral's Geek Ninja Battle Night, I'm awaiting an ok in using it. So it may change :)</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Creating A CSS3 Paper Stack</title>
      <link href="https://www.alwaystwisted.com/articles/creating-a-css3-paper-stack.html"/>
      <updated>2011-03-06T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/creating-a-css3-paper-stack.html</id>
      <content type="html">
        <![CDATA[
        <p>On January 12th 2011 I found myself like most days, browsing through the various new shots on<a href="http://www.dribbble.com/">Dribbble</a> when I came across a <a href="http://dribbble.com/shots/98799-Target-locked">nice little shot</a> by Dan Rubin.</p>
<p>I liked the little paper stack effect that <a href="http://www.twitter.com/DanRubin">Dan</a> had created for this call to action. I liked it so much I wondered if it could be created in CSS rather than having a background image with the stack. Having previously experimented with the :before and :after CSS propertie on my <a href="../post.php%EF%B9%96s=2011-01-29-css3-3d-ribbons-using-2d-transforms.html">CSS3 3D Ribbons</a> post using 2D Transforms and box-shadow.</p>
<p>So I went about the interwebs and found a rough and ready 'paper' texture and set about creating this quick example <a href="http://alwaystwisted.com/backstage/notes.html">CSS3 Paper Stack</a></p>
<p>I found a nice little 'handwritten' font from <a href="http://www.fontsquirrel.com/">font squirrel</a> to make the demo a little more realistic and aligned the text as best possible to run along the lines of the background paper. To get the most out of this demo page it'd be best to view the code source.</p>
<p>Below is a highlight of the code to keep it as simple as possible for this blog post.</p>
<p>Also note I have only tested the <a href="http://alwaystwisted.com/backstage/notes.html">demo CSS3 paper stack</a> in latest versions of Chrome, Safari, Firefox and Opera on my iMac running Snow Leopard. I have not tried this in any other browser and have noticed that Opera isn't playing ball with the -o-transform property. I could probably guess the :before and :after properties won't work correctly in IE.</p>
<p>This is just another proof of concept to show what possibilites there are with the new CSS3 properties</p>
<p>HTML</p>
<p>&lt;!doctype html&gt;</p>
<p><head></p>
<p><meta charset='UTF-8'></p>
<p></head></p>
<p>e
   <body></p>
<p><div id='notes'></div></p>
<p></body></p>
<p></html></p>
<p>CSS</p>
<p>#notes {</p>
<p>position: relative;</p>
<p>width: 320px;</p>
<p>height: 420px;</p>
<p>border:1px solid #000000;</p>
<p>-webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.8);</p>
<p>-moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.8);</p>
<p>box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.8);</p>
<p>#notes:before {</p>
<p>z-index: -1;</p>
<p>position: absolute;</p>
<p>top:3px;</p>
<p>left:0;</p>
<p>width: 320px;</p>
<p>height: 420px;</p>
<p>content: '';</p>
<p>background-color: #444;</p>
<p>border:1px solid #000000;</p>
<p>-webkit-transform: rotate(3deg);</p>
<p>-moz-transform: rotate(3deg);</p>
<p>-o-transform: rotate(3deg);</p>
<p>transform: rotate(3deg);</p>
<p>-webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.8);</p>
<p>-moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.8);</p>
<p>box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.8);</p>
<p>}</p>
<p>#notes:after {</p>
<p>z-index: -2;</p>
<p>position: absolute;</p>
<p>top:3px;</p>
<p>left:0;</p>
<p>width: 320px;</p>
<p>height: 420px;</p>
<p>content: '';</p>
<p>background-color: #444;</p>
<p>border:1px solid #000000;</p>
<p>-webkit-transform: rotate(-2deg);</p>
<p>-moz-transform: rotate(-2deg);</p>
<p>-o-transform: rotate(-2deg);</p>
<p>transform: rotate(-2deg);</p>
<p>-webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.8);</p>
<p>-moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.8);</p>
<p>box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.8);</p>
<p>}</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Don&#39;t Let Your Menu Take Over</title>
      <link href="https://www.alwaystwisted.com/articles/dont-let-your-menu-take-over.html"/>
      <updated>2011-02-20T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/dont-let-your-menu-take-over.html</id>
      <content type="html">
        <![CDATA[
        <p><img src="/images/articles/mqnav.jpg" alt="a montage of several websites on what would be a small screen showing their navigation" loading="lazy" decoding="async"></p>
<p>The <a href="http://www.w3.org/TR/css3-mediaqueries/">CSS3 Media Queries Module</a> is fast becoming the love of the 'modern web designer'. It's great, I love it. It's fantastic what you can do these days whilst creating a website compared to the nested tables I was dealing with when I first started out.</p>
<p>But there's a problem, only a slight problem but one that is increasingly annoying me (hence this little rant).</p>
<p>The iPhone is an excellant device, it's advanced web design for mobile devices at a phenomanal pace (I can remember attempting to build a WAP site, once). With the iPhone (there are other devices available) you get 320px by 480px of 'screen real estate' to play with.</p>
<h2 id="my-gripe%2Fmoan%2Frant%3F" tabindex="-1">My gripe/moan/rant?</h2>
<h2 id="a-lot-of-you-are-filling-this-space-with-your-navigation!" tabindex="-1">A lot of you are filling this space with your navigation!</h2>
<p>I use my iPhone everyday, almost too much. As my real world job is nothing to do with web design and is two miles up a farm track near the <a href="http://www.phrases.org.uk/meanings/52650.html">back of beyond</a> I access the internet, twitter, ebay and my RSS via my iPhone as that's the only access I have for at least 9 hours of the day.</p>
<p>When I visit a website, I don't mind if it doesn't use CSS3 Media Queries, hey it's only just started to get implemented. I've got my fingers so I can pinch and zoom to my hearts content, but if your site uses CSS3 Media Queries please don't show me a whole screen of your navigation to start with.</p>
<p>I know that screen size is small, I know that you think it looks good but honestly it doesn't have to be that big, you're not designing a Fisher Price 'My First Website'. The Apple <a href="http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/MobileHIG/UEBestPractices/UEBestPractices.html%23//apple_ref/doc/uid/TP40006556-CH20-SW1">Human Interface Guidelines</a> suggest an optimum size of 44px by 44px for a tappable area. That's not 44px high by 320px wide that's a 44px by 44px square. I know you're probaly saying to yourself that you can't fit the links in that space, I agree, but you can fit more than one link in a line on a screen size that has a width of 320px or more.</p>
<p>So please, be a bit careful when using Media Queries so that your site adapts to the browser window. I don't need a screen of navigation, I don't know what's on the rest of your homepage yet.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Create a CSS3 Media Queries Easter Egg</title>
      <link href="https://www.alwaystwisted.com/articles/create-a-css3-media-queries-easter-egg.html"/>
      <updated>2011-02-18T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/create-a-css3-media-queries-easter-egg.html</id>
      <content type="html">
        <![CDATA[
        <p>A day does not pass without me seeing something about CSS3 Media Queries on the Internet. Be it a new article highlighting the pros or slating the cons, a tutorial showing you how to use them to create an 'iphone version' of your website or people tweeting about the module.</p>
<p>One thing has struck me about all this recently and that is; apart from us as web designers having a poke around a fellow designer newly finished site or clients site would anyone else re-size the browsers (if possible) and notice the changes that are put in place using this part of the CSS3 spec.</p>
<p>Whilst I was designing this blog (it's a perpetual work in progress) I thought it'd be kind of cool to add a slight colour change of the main background when the browser window is re-sized or for when your on an smart phone/iPhone or a iPad/Tablet/Netbook.</p>
<p>Whilst I was using the CSS3 media queries to set my widths for the appropriate 'mobile' devices I thought I'd use the new CSS3 transitions so that people on a big screen for if and when the re-size the browser would have a nice fade between colours.</p>
<p>I set about creating a quick <a href="../playground/media-queries-easter-egg-demo.html">test demo page</a> to see what would happen, the css for this page is shown below.</p>
<p>Don't forget to resize your browser or flip your iPhone/iPad.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">body</span> <span class="token punctuation">{</span>
	<span class="token property">height</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
	<span class="token property">width</span><span class="token punctuation">:</span>100%<span class="token punctuation">;</span>
	<span class="token property">background-color</span><span class="token punctuation">:</span> #ccc<span class="token punctuation">;</span>
	<span class="token property">-webkit-transition</span><span class="token punctuation">:</span> all 2s ease<span class="token punctuation">;</span> <span class="token comment">/* Saf3.2+, Chrome */</span>
	<span class="token property">-moz-transition</span><span class="token punctuation">:</span> all 2s ease<span class="token punctuation">;</span> <span class="token comment">/* FF3.7+ */</span>
	<span class="token property">-o-transition</span><span class="token punctuation">:</span> all 2s ease<span class="token punctuation">;</span> <span class="token comment">/* Opera 10.5 */</span>
	<span class="token property">transition</span><span class="token punctuation">:</span> all 2s ease<span class="token punctuation">;</span>

	<span class="token atrule"><span class="token rule">@media</span> screen <span class="token keyword">and</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span>320px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
		<span class="token selector">body</span> <span class="token punctuation">{</span> 
			<span class="token property">background-color</span><span class="token punctuation">:</span> black<span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>

	<span class="token atrule"><span class="token rule">@media</span> screen <span class="token keyword">and</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span>480px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
		<span class="token selector">body</span> <span class="token punctuation">{</span>
			<span class="token property">background-color</span><span class="token punctuation">:</span> red<span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>

	<span class="token atrule"><span class="token rule">@media</span> screen <span class="token keyword">and</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span>768px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
		<span class="token selector">body</span> <span class="token punctuation">{</span>
			<span class="token property">background-color</span><span class="token punctuation">:</span> blue<span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>

	<span class="token atrule"><span class="token rule">@media</span> screen <span class="token keyword">and</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span>1024px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
		<span class="token selector">body</span> <span class="token punctuation">{</span>
			<span class="token property">background-color</span><span class="token punctuation">:</span> green<span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span></code></pre>
<p>As you can see from the demo it was a quick 'test case' to see the idea in a really obvious way. On this site, hopefully, it is a little more subtle.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Fuse 2 Fonts and get to SXSWi</title>
      <link href="https://www.alwaystwisted.com/articles/fuse-2-fonts-and-get-to-sxswi.html"/>
      <updated>2011-02-17T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/fuse-2-fonts-and-get-to-sxswi.html</id>
      <content type="html">
        <![CDATA[
        <p>So, I didn't win the <a href="http://netmag.co.uk/">.net magazine</a> competition for a pair of tickets to SXSWi this year.</p>
<p>Thanks to <a href="http://www.twitter.com/candiRSX">Candi</a> I've just entered a competition at <a href="http://fontfuse.webink.com/">Font Fuse</a> for the chance to get some kick-ass VIP tickets to SXSWi. I probably won't win, I never win. Well, I haven't won anything since 1988 when I got a bunch of Panini stickers and the 1988 American Football sticker album, but I digress.</p>
<p><img src="/images/articles/simpleelegance.png" alt="simple elegance image" loading="lazy" decoding="async"></p>
<p>Sure picking two fonts can be like taking candy from a baby or it can be the most difficult thing you have to suss out. I generally stick to one font pair in almost all the work I do when I start and I'm not entirely sure if the fonts I've chosen for this piece of the internet I call mine are entirely 'right'.</p>
<p>I was thinking that really what both fonts need to do is</p>
<ol>
<li>complement each other</li>
<li>be 'easy' on the eye</li>
<li>not be imposing on the page</li>
<li>be simple</li>
<li>be elegant</li>
</ol>
<p>Having a quick look at the vast amount of fonts available i picked my two favourites for the task. I chose some nice blues for the background and the heading and body text.</p>
<p>I wasn't too satisfied with the standard text placed in the body so I found a nice little quote from Robert Louis Stevenson</p>
<blockquote>
<p>The web, then, or the pattern, a web at once sensuous and logical, an elegant and pregnant texture: that is style, that is the foundation of the art of literature.</p>
</blockquote>
<p>So if you have a spare 5 minutes why not take a look at the competion, have a go yourself, look at other font pairings for some great typographic inspiration or just <a href="http://fontfuse.webink.com/pairing/stu/simple-elegance">vote for my pairing</a>.</p>

      ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>CSS3 3D Ribbons using 2D Transforms</title>
      <link href="https://www.alwaystwisted.com/articles/css3-3d-ribbons-using-2d-transforms.html"/>
      <updated>2011-01-29T00:00:00Z</updated>
      <id>https://www.alwaystwisted.com/articles/css3-3d-ribbons-using-2d-transforms.html</id>
      <content type="html">
        <![CDATA[
        <p>&lt;&gt; It's a 'trend' of the moment which seems to be fading slightly but you probably won't be able to go a day, let alone an hour, without seeing some form of 'ribbon' being employed in the design of a website.</p>
<p>These are usually created with graphics software such as Photoshop or Fireworks but with the modern browsers of today and the great tools that we can use within the CSS3 spec we are able to create this effect using just the code.</p>
<p>I got inspired to try this out by two things. First was a post from <a href="http://www.pvmgarage.com/2010/01/how-to-create-depth-and-nice-3d-ribbons-only-using-css3/">PVM Garage</a> showing you how to add a nice 3D ribbon to your page using CSS3. I thought this was really good but I wasn't happy with the <a href="http://en.wikipedia.org/wiki/Tag_soup">'tag soup'</a> that was being used to get the effect working. I then, through <a href="http://www.twitter.com/Sturobson">Twitter</a> saw that <a href="http://www.twitter.com/Matthamm">Matt Hamm</a> had created some cool <a href="http://www.matthamm.com/notebook/?p=7">CSS3 box-shadow page curls</a> and seeing that he was using the :before and :after elements attempted to recreate the 3D ribbon with just one DIV.</p>
<p>I posted a whole page in my <a href="http://www.alwaystwisted.com/blog/backstage.php">back stage area</a> where I will be putting all of my 'experiments' in the future (note, this whole site is a in current state of 'work in progress').</p>
<p>Then the latest copy of <a href="http://www.netmag.co.uk/">.net (issue 212)</a> and there was a tutorial for 3D ribbons using CSS like the PVM Garage example I thought I'd better create a 'proper post' on what I did just after Christmas 2010.</p>
<p><img src="/images/articles/css3-3d-ribbon.png" alt="3D ribbons example" loading="lazy" decoding="async"></p>
<p>The code below would create something along the lines of what is shown in the image above. As you can see on the <a href="../backstage/css3-ribbon.html">backstage page</a> there are some more examples of what is possible using CSS3 2D transforms, box-shadow, rounded corners and CSS :before and :after elements.</p>
<h3 id="html" tabindex="-1">HTML</h3>
<p>&lt;!doctype html&gt;</p>
<p><head></p>
<p><meta charset='UTF-8'></p>
<p></head></p>
<p><body></p>
<p><div id ='container'></p>
<p><div id='ribbon'></div></p>
<p></div></p>
<p></body></p>
<p></html></p>
<h3 id="css" tabindex="-1">CSS</h3>
<p>#ribbon {</p>
<p>position: relative;</p>
<p>top:40px;</p>
<p>left:-20px;</p>
<p>width: 960px;</p>
<p>height:100px;</p>
<p>background-color: #999;</p>
<p>float: left;</p>
<p>-webkit-box-shadow: 0px 0px 2px #000;</p>
<p>-moz-box-shadow: 0px 0px 2px #000;</p>
<p>box-shadow: 0px 0px 2px #000;</p>
<p>border-bottom: 1px solid #000;</p>
<p>}</p>
<p>#ribbon:before {</p>
<p>z-index: -1;</p>
<p>position: absolute;</p>
<p>top:10px;</p>
<p>left:0;</p>
<p>width: 20px;</p>
<p>height: 101px;</p>
<p>content: '';</p>
<p>background-color: #444;</p>
<p>-webkit-transform: skewY(45deg);</p>
<p>-moz-transform: skewY(45deg);</p>
<p>-o-transform: skewY(45deg);</p>
<p>transform: skewY(45deg);</p>
<p>-webkit-box-shadow: inset 1px -1px 3px #000, 1px 1px 3px #000;</p>
<p>-moz-box-shadow: inset 1px -1px 3px #000, 1px 1px 3px #000;</p>
<p>box-shadow: inset 1px -1px 3px #000, 1px 1px 3px #000;</p>
<p>}</p>
<p>#ribbon:after {</p>
<p>z-index: -2;</p>
<p>position: absolute;</p>
<p>top:10px;</p>
<p>right:0;</p>
<p>width: 20px;</p>
<p>height: 101px;</p>
<p>content: '';</p>
<p>background-color: #444;</p>
<p>-webkit-transform: skewY(-45deg);</p>
<p>-moz-transform: skewY(-45deg);</p>
<p>-o-transform: skewY(-45deg);</p>
<p>transform: skewY(-45deg);</p>
<p>-webkit-box-shadow: inset 1px -1px 3px #000, 1px 1px 3px #000;</p>
<p>-moz-box-shadow: inset 1px -1px 3px #000, 1px 1px 3px #000;</p>
<p>box-shadow: inset 1px -1px 3px #000, 1px 1px 3px #000;</p>
<p>}</p>

      ]]>
      </content>
    </entry>
  
</feed>