<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Geoff Rich</title>
    <description>The latest articles on DEV Community by Geoff Rich (@geoffrich).</description>
    <link>https://dev.to/geoffrich</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F507465%2F67fcde38-4c9b-4b2e-b07e-5e5c5c1c30c5.jpg</url>
      <title>DEV Community: Geoff Rich</title>
      <link>https://dev.to/geoffrich</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/geoffrich"/>
    <language>en</language>
    <item>
      <title>Assorted Svelte demos: conditional wrappers, page transitions, actions</title>
      <dc:creator>Geoff Rich</dc:creator>
      <pubDate>Fri, 08 Jul 2022 15:33:56 +0000</pubDate>
      <link>https://dev.to/geoffrich/assorted-svelte-demos-conditional-wrappers-page-transitions-actions-2ec4</link>
      <guid>https://dev.to/geoffrich/assorted-svelte-demos-conditional-wrappers-page-transitions-actions-2ec4</guid>
      <description>&lt;p&gt;Over the past couple months I’ve been posting some Svelte demos to Twitter. I’ve been meaning to turn some of them into full blog posts, but I’ve been quite busy so that hasn’t happened yet.&lt;/p&gt;

&lt;p&gt;Since Twitter is ephemeral, I wanted to write a quick post capturing these demos for future reference. No in-depth explanations here—I’ll be keeping it pretty short. However, some of these might be given a full write-up in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using svelte:element to create a reusable wrapper
&lt;/h2&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
    &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__two-pics"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3HqvANoK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/FSp7S2mUYAEMssA.jpg" alt="unknown tweet media content"&gt;
    &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--IDXB6JXE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1507874532232609792/3Tz-x2Y3_normal.jpg" alt="Geoff Rich profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Geoff Rich
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @geoffrich_
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      With the release of svelte:element, you can now create a reusable Wrapper component that can conditionally wrap its children with any HTML tag!&lt;br&gt;&lt;br&gt;You could make this component before, but would need to hard-code the wrapper tag. 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      17:35 PM - 13 May 2022
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1525167882396569601" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1525167882396569601" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1525167882396569601" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;&lt;a href="https://svelte.dev/docs#template-syntax-svelte-element"&gt;svelte:element&lt;/a&gt; was released in Svelte 3.47.0, which allows you to dynamically render a given HTML tag. See the &lt;a href="https://svelte.dev/tutorial/svelte-element"&gt;official tutorial section&lt;/a&gt; for more details. I used it to create a custom &lt;code&gt;&amp;lt;Wrapper&amp;gt;&lt;/code&gt; component that can conditionally wrap its children.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;wrap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

{#if wrap}
&lt;span class="nt"&gt;&amp;lt;svelte:element&lt;/span&gt; &lt;span class="na"&gt;this=&lt;/span&gt;&lt;span class="s"&gt;"{tag}"&lt;/span&gt; &lt;span class="err"&gt;{...$$&lt;/span&gt;&lt;span class="na"&gt;restProps&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svelte:element&amp;gt;&lt;/span&gt;
{:else}
&lt;span class="nt"&gt;&amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;&lt;/span&gt;
{/if}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it can be used like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Wrapper&lt;/span&gt; &lt;span class="na"&gt;tag=&lt;/span&gt;&lt;span class="s"&gt;"details"&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="na"&gt;wrap&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;Yar 🦜 🏴‍☠️&lt;span class="nt"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    Prow scuttle parrel provost Sail ho shrouds spirits boom mizzenmast yardarm. Pinnace
    holystone mizzenmast quarter crow's nest nipperkin grog yardarm hempen halter furl.
    Swab barque interloper chantey doubloon starboard grog black jack gangway rutters.
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    Deadlights jack lad schooner scallywag dance the hempen jig carouser broadside cable
    strike colors. Bring a spring upon her cable holystone blow the man down spanker
    Shiver me timbers to go on account lookout wherry doubloon chase. Belay yo-ho-ho
    keelhaul squiffy black spot yardarm spyglass sheet transom heave to.
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Wrapper&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this component, you’d have to introduce some significant duplication.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{#if wrap}
&lt;span class="nt"&gt;&amp;lt;details&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;Yar 🦜 🏴‍☠️&lt;span class="nt"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    Prow scuttle parrel provost Sail ho shrouds spirits boom mizzenmast yardarm. Pinnace
    holystone mizzenmast quarter crow's nest nipperkin grog yardarm hempen halter furl.
    Swab barque interloper chantey doubloon starboard grog black jack gangway rutters.
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/details&amp;gt;&lt;/span&gt;
{:else}
&lt;span class="nt"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;Yar 🦜 🏴‍☠️&lt;span class="nt"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
  Prow scuttle parrel provost Sail ho shrouds spirits boom mizzenmast yardarm. Pinnace
  holystone mizzenmast quarter crow's nest nipperkin grog yardarm hempen halter furl. Swab
  barque interloper chantey doubloon starboard grog black jack gangway rutters.
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{/if}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(For the purposes of this demo, I rendered a summary element even when there’s no details. This is not actually valid HTML — you’d probably want to swap it out for an h2 or something when there’s no details.)&lt;/p&gt;

&lt;p&gt;There's a &lt;a href="https://svelte.dev/repl/983851f4fb7044e8b5d66a53ca0b356b?version=3.48.0"&gt;full demo&lt;/a&gt; in the REPL with some more examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Native page transitions in SvelteKit
&lt;/h2&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OUTvJV7A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1534978671852650496/pu/img/pDxZCUG67ia6o0GM.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--IDXB6JXE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1507874532232609792/3Tz-x2Y3_normal.jpg" alt="Geoff Rich profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Geoff Rich
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @geoffrich_
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Played around with the new web API for page transitions in SvelteKit and the results are pretty slick! Chrome Canary only (w/ a flag) for now.&lt;br&gt;&lt;br&gt;This all works using SvelteKit's beforeNavigate/afterNavigate hooks in the top-level __layout + `document.createDocumentTransition` 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      19:28 PM - 09 Jun 2022
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1534980702785003520" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1534980702785003520" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1534980702785003520" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;I took the experimental page transition API (a.k.a. &lt;a href="https://github.com/WICG/shared-element-transitions"&gt;shared element transitions&lt;/a&gt;) for a test drive with SvelteKit, and the result was pretty slick. You’ll need Chrome Canary with the &lt;code&gt;chrome://flags/#document-transition&lt;/code&gt; flag enabled if you want to try this one out yourself — the original tweet has a video if you don’t want to jump through those hoops. There’s a &lt;a href="https://sveltekit-shared-element-transitions-codelab.vercel.app/fruits"&gt;live demo&lt;/a&gt; and a &lt;a href="https://github.com/geoffrich/sveltekit-shared-element-transitions"&gt;GitHub repo&lt;/a&gt; if you want to see how it was accomplished.&lt;/p&gt;

&lt;p&gt;I was able to implement it using SvelteKit’s &lt;code&gt;beforeNavigate&lt;/code&gt; and &lt;code&gt;afterNavigate&lt;/code&gt; hooks in a top-level __layout. It started out as a port of the &lt;a href="https://codelabs.developers.google.com/create-an-instant-and-seamless-web-app#5"&gt;shared element transitions Codelab&lt;/a&gt; but I added some extra features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;transitions to and from the list page (the original only transitioned to the details page, not from it)&lt;/li&gt;
&lt;li&gt;transitions when the browser back &amp;amp; forward buttons are clicked&lt;/li&gt;
&lt;li&gt;respects reduced motion by not playing the transitions when requested&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I came back to this recently and &lt;a href="https://github.com/geoffrich/sveltekit-shared-element-transitions/commit/7de6f37bd07f9dd69af2e0bb59e4285f879d2143"&gt;refactored it&lt;/a&gt; to use a custom navigation store that made the logic a lot easier to follow.&lt;/p&gt;

&lt;p&gt;This one will likely get a full write-up sooner rather than later, since I’ll be presenting it at a meetup in a couple weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Action to detect when focus leaves an element
&lt;/h2&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m0uugK3p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1537124783422177281/pu/img/GWzFOJm34GUKFMp5.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--IDXB6JXE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1507874532232609792/3Tz-x2Y3_normal.jpg" alt="Geoff Rich profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Geoff Rich
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @geoffrich_
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Wrote a quick li'l Svelte action to detect when focus leaves an element (or its children). This lets me autoclose a menu when a user tabs out of it.&lt;br&gt;&lt;br&gt;(video alt: a menu appears showing a list of links. I tab through the links and the menu closes when I tab away from the last one) 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      17:31 PM - 15 Jun 2022
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1537125628327038976" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1537125628327038976" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1537125628327038976" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;I was working on accessibility improvements to the new &lt;a href="https://learn.svelte.dev"&gt;learn.svelte.dev&lt;/a&gt; site and needed to automatically close a pop-up menu when a user tabbed out of it. Otherwise, the user’s focus would move behind the menu and they couldn’t see where they are on the page. I ended up implementing it as an action. Here’s what it looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleFocusLeave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleFocusIn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activeElement&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;focusin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleFocusIn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;focusin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleFocusIn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see it in action, see &lt;a href="https://svelte.dev/repl/77100d6479594811a833eff2315dd1f4?version=3.48.0"&gt;the demo in the Svelte REPL&lt;/a&gt; or interact with the tutorial menu on &lt;a href="https://learn.svelte.dev"&gt;learn.svelte.dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This was inspired by a similar approach from Andy Bell in a &lt;a href="https://piccalil.li/tutorial/build-a-fully-responsive-progressively-enhanced-burger-menu/#:~:text=The%20next%20part%20is%20an,force%20the%20menu%20closed%2C%20immediately."&gt;tutorial on building a burger menu&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recursive Svelte action
&lt;/h2&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
    &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__two-pics"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EJAUYHOq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/FWbpTVlUcAAoVfm.jpg" alt="unknown tweet media content"&gt;
    &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--IDXB6JXE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1507874532232609792/3Tz-x2Y3_normal.jpg" alt="Geoff Rich profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Geoff Rich
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @geoffrich_
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Normally, you apply Svelte actions to single HTML elements with. But what if you want to apply the same action to a root node and all of its children?&lt;br&gt;&lt;br&gt;You could manually apply the action to each node, or you could write a higher-order action that recursively does this for you. 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      16:02 PM - 29 Jun 2022
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1542176620303118336" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1542176620303118336" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1542176620303118336" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Normally, you apply Svelte actions to single HTML elements with &lt;code&gt;use:action&lt;/code&gt;. But what if you want to apply the same action to a root node and all of its children? You could manually apply the action to each node, or you could write a higher-order action that recursively does this for you. I was able to implement this using a single action and a MutationObserver to track updates. Here’s what it looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;recurse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;act&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;filterForElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ELEMENT_NODE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MutationObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mutations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;mutations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mutation&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;handleAdditions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addedNodes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;handleRemovals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removedNodes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleAdditions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addedNodes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;filterForElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addedNodes&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;observed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleRemovals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;removedNodes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;filterForElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;removedNodes&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;observed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;?.();&lt;/span&gt;
      &lt;span class="nx"&gt;observed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;childList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;subtree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;observed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newParams&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newParams&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;observed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the &lt;a href="https://svelte.dev/repl/b7c95fd6876d4d7382777fa6d1a31117?version=3.48.0"&gt;Svelte REPL&lt;/a&gt; for an example of it in action. The demo is a little contrived — I’m still not entirely sure how this would be useful. I just thought it was a neat idea and had to get it out of my head.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>svelte</category>
    </item>
    <item>
      <title>Svelte quick tip: Style prop defaults</title>
      <dc:creator>Geoff Rich</dc:creator>
      <pubDate>Thu, 28 Apr 2022 15:08:28 +0000</pubDate>
      <link>https://dev.to/geoffrich/svelte-quick-tip-style-prop-defaults-3m74</link>
      <guid>https://dev.to/geoffrich/svelte-quick-tip-style-prop-defaults-3m74</guid>
      <description>&lt;p&gt;Svelte has a built-in solution for component theming using &lt;a href="https://svelte.dev/docs#template-syntax-component-directives---style-props"&gt;style props&lt;/a&gt;. So, you can use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties"&gt;CSS custom properties&lt;/a&gt; in your component styles...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    I have something important to say.
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--line-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c"&gt;/* Decorative styles */&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60ch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...and easily set them from outside the component using style props.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;TextBox&lt;/span&gt; &lt;span class="na"&gt;--line-color=&lt;/span&gt;&lt;span class="s"&gt;"mediumspringgreen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/TextBox&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what if you want your style to have a default value? The custom property &lt;code&gt;var&lt;/code&gt; syntax takes a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties#custom_property_fallback_values"&gt;second argument&lt;/a&gt; that sets a fallback if the property is not defined. So, if you wanted the default border color to be &lt;code&gt;darkred&lt;/code&gt;, you could do the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--line-color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;darkred&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this can get verbose if you want to use &lt;code&gt;--line-color&lt;/code&gt; in multiple places, with the same fallback. If you want to update the default value, you have to do it multiple places!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--line-color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;darkred&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&lt;/span&gt; &lt;span class="n"&gt;wavy&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--line-color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;darkred&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There’s two ways to refactor this to make it less verbose. First, you could introduce another custom property for the default value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--line-color-default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;darkred&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--line-color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--line-color-default&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&lt;/span&gt; &lt;span class="n"&gt;wavy&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--line-color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--line-color-default&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it so there’s one place to &lt;em&gt;change&lt;/em&gt; the default value, but you still have to provide the second argument to &lt;code&gt;var&lt;/code&gt; every time you reference &lt;code&gt;--line-color&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Instead, my recommended approach would be to introduce another custom property that represents &lt;em&gt;either line-color or the fallback&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--_line-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--line-color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;darkred&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--_line-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&lt;/span&gt; &lt;span class="n"&gt;wavy&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--_line-color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now you have two variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--line-color&lt;/code&gt; is the user-supplied theme value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--_line-color&lt;/code&gt; is what we use in our styles, and will either be the user-supplied value (if defined) or the default color&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see this in action in this &lt;a href="https://svelte.dev/repl/c14650e187bb48e9a3e168b9955268ea?version=3.47.0"&gt;Svelte REPL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You only need to introduce a variable like &lt;code&gt;--_line-color&lt;/code&gt; if you plan on using the theme variable multiple places. Otherwise, it’s perfectly fine to set the fallback where you use the property, as in the first example.&lt;/p&gt;

&lt;p&gt;The technique on display here is not unique to Svelte, and can be applied anywhere you use custom properties. However, it's of particular interest with Svelte, since custom properties are the recommended way of theming a component.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>svelte</category>
    </item>
    <item>
      <title>4 tips for cleaner Svelte components</title>
      <dc:creator>Geoff Rich</dc:creator>
      <pubDate>Wed, 06 Apr 2022 16:17:26 +0000</pubDate>
      <link>https://dev.to/geoffrich/4-tips-for-cleaner-svelte-components-1gln</link>
      <guid>https://dev.to/geoffrich/4-tips-for-cleaner-svelte-components-1gln</guid>
      <description>&lt;p&gt;I've helped a few devs at my company get started with Svelte, and I love seeing how easy it is for them to pick it up and start being productive. However, I've noticed a few areas where they write verbose code without realizing that Svelte has a cleaner way to do the same thing.&lt;/p&gt;

&lt;p&gt;Drawing on that experience, I've collected four ways to write cleaner and Svelte-ier component code. I think these will be especially helpful if you're new to Svelte, though more experienced devs might learn something too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Work with the component template, not against it
&lt;/h2&gt;

&lt;p&gt;When people are new to Svelte (or front-end frameworks in general), sometimes I see them use &lt;code&gt;querySelector&lt;/code&gt; in their component code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;submitButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.submit-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;submitButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;submitButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Submitting...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"submit-button"&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;"{handleSubmit}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Submit
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Does it work? Sure. Is it a good idea? &lt;strong&gt;Absolutely not.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I &lt;em&gt;think&lt;/em&gt; this happens because devs see the script tag and assume they should treat it like an inline script in a regular HTML document. But the script block in Svelte isn't just a script tag—it's a script tag with superpowers. You aren't limited to how you would interact with elements in vanilla JS.&lt;/p&gt;

&lt;p&gt;The benefit of using Svelte (and other modern frameworks) is that your template can be driven by your component state. Instead of manually querying for elements, you can instead express that logic directly in your template. Here's how I would rewrite the first example to consolidate the logic inside the template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;submitting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;submitting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;"{handleSubmit}"&lt;/span&gt; &lt;span class="na"&gt;disabled=&lt;/span&gt;&lt;span class="s"&gt;"{submitting}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  {submitting ? 'Submitting...' : 'Submit'}
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes your components much easier to reason about. You can look at the template and understand all the different states a component can be in, instead of trying to track down all the places where you might be updating something in the template.&lt;/p&gt;

&lt;p&gt;(In addition, by writing &lt;code&gt;document.querySelector&lt;/code&gt; you could potentially retrieve an element in a completely different component than what you're working in. Sometimes that's what you want, but usually it's not.)&lt;/p&gt;

&lt;p&gt;Because of this, it's a good rule of thumb to avoid using &lt;code&gt;querySelector&lt;/code&gt;, &lt;code&gt;querySelectorAll&lt;/code&gt;, or any imperative query methods in your Svelte component. This isn't to say that you should &lt;em&gt;never&lt;/em&gt; use them. However, using a feature built-in to Svelte would often be a better solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you're updating text or attributes of an element inside your component, you should express it in your component template instead of querying for the element.&lt;/li&gt;
&lt;li&gt;If you need a reference to a particular DOM element in your component (which is especially common when integrating vanilla JS libraries), you should first try using &lt;code&gt;bind:this&lt;/code&gt; or an action.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only once you've considered and ruled out these methods should you reach for &lt;code&gt;querySelector&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two-way binding is awesome
&lt;/h2&gt;

&lt;p&gt;If you come to Svelte from React, you might instinctively write your form inputs this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Name&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"{value}"&lt;/span&gt; &lt;span class="na"&gt;on:input=&lt;/span&gt;&lt;span class="s"&gt;"{handleInput}"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
  The value is {value}
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works, but is considered by many Svelte devs to be too much boilerplate. In Svelte, you can remove a lot of this code by using &lt;code&gt;bind:value&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script&amp;gt;
  let value = '';
&amp;lt;/script&amp;gt;

&amp;lt;label for="name"&amp;gt;Name&amp;lt;/label&amp;gt;
&amp;lt;input id="name" type="text" bind:value /&amp;gt;

&amp;lt;p&amp;gt;
  The value is {value}
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can significantly reduce the amount of code you write, especially if you have a lot of form inputs. And &lt;a href="https://svelte.dev/blog/write-less-code"&gt;less code means fewer bugs.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also use two-way binding &lt;a href="https://svelte.dev/docs#template-syntax-component-directives-bind-property"&gt;with component props&lt;/a&gt;. You need to be more careful with this kind of binding, since overusing it can make it hard to understand where state is being changed in your application. This is especially true if you use two-way binding across multiple layers of components, since any component in that tree could change the state for every component that's bound to it. But for form elements (and components that wrap form elements), two-way binding is the right choice.&lt;/p&gt;

&lt;p&gt;For another perspective on this, see &lt;a href="https://imfeld.dev/writing/how_svelte_makes_two_way_binding_safe"&gt;"How Svelte Makes Two-Way Binding Safe”&lt;/a&gt; by Daniel Imfeld.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scoped styles let you write slimmer styles
&lt;/h2&gt;

&lt;p&gt;In Svelte, styles are &lt;a href="https://svelte.dev/tutorial/styling"&gt;automatically scoped&lt;/a&gt;. You can write styles in a component and be assured that they won't leak out and unexpectedly affect another part of the application.&lt;/p&gt;

&lt;p&gt;If you're used to working in projects without component-scoped styles, you might be used to writing lengthy class names to ensure that they don't conflict with styles in another part of the application. But in Svelte, you don't need to worry about that!&lt;/p&gt;

&lt;p&gt;It's perfectly okay to use shorter, more generic class names like “heading” or “wrapper” in your Svelte component, since you can be confident that those styles won't accidentally apply to an element somewhere else. You can even target HTML tag names like &lt;code&gt;p&lt;/code&gt; and &lt;code&gt;button&lt;/code&gt; safely, though whether you should do this depends on the component.&lt;/p&gt;

&lt;p&gt;For example, in the following example, I don't need to add a class to the button and paragraph just to style them. Since I want to style all paragraphs and buttons &lt;em&gt;in this component&lt;/em&gt;, I can just target &lt;code&gt;p&lt;/code&gt; and &lt;code&gt;button&lt;/code&gt; directly, and elements outside this component won't be affected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    Katamari Damacy (lit. 'Clump Spirit') is a
    third-person puzzle-action video game developed
    and published by Namco for the PlayStation 2.
    It was released in Japan in March 2004 and in North
    America in September 2004.
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    That's neat!
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;limegreen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;hotpink&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're interested in how this scoping works, I did a deep dive on &lt;a href="https://geoffrich.net/posts/svelte-scoped-styles/"&gt;how Svelte scopes styles&lt;/a&gt; last year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't miss out on all of Svelte's syntax sugar
&lt;/h2&gt;

&lt;p&gt;Svelte has a lot of built-in niceties to reduce boilerplate for common tasks. Here are some that you might have overlooked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instead of doing manual string interpolation to add and remove classes or set inline styles, you can use &lt;a href="https://svelte.dev/tutorial/classes"&gt;class:&lt;/a&gt; and &lt;a href="https://geoffrich.net/posts/style-directives/"&gt;style:&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Instead of setting up an &lt;code&gt;input&lt;/code&gt; listener and keeping local state in sync, you can use &lt;a href="https://svelte.dev/tutorial/text-inputs"&gt;bind:value&lt;/a&gt;. Similarly, instead of wiring up a &lt;code&gt;change&lt;/code&gt; listener to a group of radio buttons, you can use &lt;a href="https://svelte.dev/tutorial/group-inputs"&gt;bind:group&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Instead of writing the same expression multiple times inside an &lt;code&gt;#each&lt;/code&gt; block, you can use &lt;a href="https://geoffrich.net/posts/local-constants/"&gt;@const&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Instead of &lt;a href="https://svelte.dev/tutorial/bind-this"&gt;bind:this and onMount&lt;/a&gt; when you need a reference to a particular DOM node, you can &lt;a href="https://blog.logrocket.com/svelte-actions-introduction/"&gt;use an action&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Either option will functionally produce the same result, but the second involves less code and more readable components (especially if you can get rid of tricky string interpolation).&lt;/p&gt;

&lt;p&gt;I recommend giving the &lt;a href="https://svelte.dev/docs"&gt;Svelte docs&lt;/a&gt; a full read-through, especially if it's been a while since you went through the tutorial. You might not know what you're missing!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;It was fun to do a “quick hits” style of article for this. There's a few more tips I'm chewing over, so you might see a follow-up article at some point.&lt;/p&gt;

&lt;p&gt;Thanks to everyone who responded to my “common Svelte antipatterns” &lt;a href="https://twitter.com/geoffrich_/status/1488955388808421380"&gt;thread on Twitter&lt;/a&gt; (that also somehow devolved into a 🐫 case vs. 🐍 case debate). Go check that out for some other folks' ideas on what makes for cleaner Svelte components!&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Local constants in Svelte with the @const tag</title>
      <dc:creator>Geoff Rich</dc:creator>
      <pubDate>Tue, 08 Mar 2022 16:41:07 +0000</pubDate>
      <link>https://dev.to/geoffrich/local-constants-in-svelte-with-the-const-tag-35g2</link>
      <guid>https://dev.to/geoffrich/local-constants-in-svelte-with-the-const-tag-35g2</guid>
      <description>&lt;p&gt;&lt;a href="https://geoffrich.net/posts/style-directives/"&gt;Style directives&lt;/a&gt; weren't the only new feature introduced in Svelte 3.46! Let's take a look at the other recent addition to Svelte: &lt;a href="https://svelte.dev/docs#template-syntax-const"&gt;the @const tag&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Let's say you're displaying a list of boxes and calculating their areas, and also want to apply some styling when the area is a certain amount. You might think of doing something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;boxes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

{#each boxes as box}
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class:big=&lt;/span&gt;&lt;span class="s"&gt;{box.width&lt;/span&gt; &lt;span class="na"&gt;*&lt;/span&gt; &lt;span class="na"&gt;box.height&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 10}&amp;gt;
    {box.width} * {box.height} = {box.width * box.height}
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{/each}

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.big&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we compute &lt;code&gt;box.width * box.height&lt;/code&gt; twice — once to display it, and once in the &lt;code&gt;class:big&lt;/code&gt; directive. Even though the value hasn't changed, the browser still has to compute it twice. While this isn't an issue with a simple calculation like this, it could impact performance if the calculation was more intensive. It also introduces duplication into the code. If you needed to use the area more times (e.g. to apply different CSS classes), it would further compound these issues.&lt;/p&gt;

&lt;p&gt;(As an aside, this is only a problem because we're inside an #each block. If there was only a single box, we could compute the area once in the script block and be done with it.)&lt;/p&gt;

&lt;p&gt;Before the const tag was introduced, there were a few ways to work around this issue. You could create a helper function to compute the value...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;boxes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

{#each boxes as box}
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class:big=&lt;/span&gt;&lt;span class="s"&gt;{area(box)&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 10}&amp;gt;
    {box.width} * {box.height} = {area(box)}
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{/each}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reduces the duplication, but it will still perform the computation multiple times unless you implement some form of &lt;a href="https://kyleshevlin.com/memoization"&gt;memoization&lt;/a&gt;. Again, this is likely not a concern for a simple calculation like area, but it would be for more expensive calculations.&lt;/p&gt;

&lt;p&gt;You could also create a new array that pre-computes the property you want...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;boxes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mappedBoxes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;boxes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

{#each mappedBoxes as box}
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class:big=&lt;/span&gt;&lt;span class="s"&gt;{box.area&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 10 }&amp;gt;
    {box.width} * {box.height} = {box.area}
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{/each}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works, but feels a little awkward, and now you have to loop over the array multiple times. In a large component, you'd also have to jump between the template where the variable is used and the script where it's defined when making changes.&lt;/p&gt;

&lt;p&gt;One final option is to extract a new component...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Box&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Box.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;boxes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

{#each boxes as box}
  &lt;span class="nt"&gt;&amp;lt;Box&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="na"&gt;box&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/Box&amp;gt;&lt;/span&gt;
{/each}

&lt;span class="c"&gt;&amp;lt;!-- Box.svelte --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;area&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class:big=&lt;/span&gt;&lt;span class="s"&gt;{area&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 10}&amp;gt;
  {box.width} * {box.height} = {area}
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... but this seems like overkill for such a simple use-case.&lt;/p&gt;

&lt;p&gt;Before Svelte 3.46, you would need to choose one of these options. Now, there's an additional solution: &lt;a href="https://svelte.dev/docs#template-syntax-const"&gt;local constants&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution: local constants
&lt;/h2&gt;

&lt;p&gt;Instead of adding logic to the script block, you can declare a constant directly in the markup itself with &lt;code&gt;@const&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{#each boxes as box}
  {@const area = box.width * box.height}
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class:big=&lt;/span&gt;&lt;span class="s"&gt;{area&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 10}&amp;gt;
    {box.width} * {box.height} = {area}
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{/each}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is more readable, since the value is declared directly where it is used, and more efficient, since it only computes the value once.&lt;/p&gt;

&lt;p&gt;The name “const” was chosen because it behaves like a constant: it is read-only and can't be assigned to. Also, like the native JavaScript &lt;code&gt;const&lt;/code&gt;, it is scoped to the block it was declared in. The following template produces compiler errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{#each boxes as box}
  {@const area = box.width * box.height}
    &lt;span class="c"&gt;&amp;lt;!-- Error: 'area' is declared using {@const ...} and is read-only --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;on:hover=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; area = 50}&amp;gt;
        {box.width} * {box.height} = {area}
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{/each}
&lt;span class="c"&gt;&amp;lt;!-- 'area' is not defined --&amp;gt;&lt;/span&gt;
{area}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Despite the similarity to the JavaScript keyword, there is no corresponding &lt;code&gt;let&lt;/code&gt; or &lt;code&gt;var&lt;/code&gt; tag. Also, unlike &lt;code&gt;const&lt;/code&gt; in JavaScript, variables declared with &lt;code&gt;@const&lt;/code&gt; can be used before they are declared. The following example is valid, despite &lt;code&gt;area&lt;/code&gt; being used before it's declared with &lt;code&gt;@const&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{#each boxes as box}
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    {box.width} * {box.height} = {area}
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  {@const area = box.width * box.height}
{/each}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Destructuring inside #each
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@const&lt;/code&gt; will also make it easier to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment"&gt;destructure&lt;/a&gt; objects inside #each blocks. Currently, you can destructure a variable inside an #each block like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{#each boxes as {width, height}}
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{width} * {height} = {width * height}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{/each}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, once you do that, you don't have a reference to the original object any more. If you want to use the original object (e.g. to pass to another component), you need to recreate it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{#each boxes as {width, height}}
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{width} * {height} = {width * height}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Box&lt;/span&gt; &lt;span class="na"&gt;box=&lt;/span&gt;&lt;span class="s"&gt;{{width,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="err"&gt;}}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
{/each}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If properties are added or removed from the original object, you need to keep this second object up-to-date as well. This can be easy to forget.&lt;/p&gt;

&lt;p&gt;Now you can destructure the object with &lt;code&gt;@const&lt;/code&gt;, while keeping a reference to the original object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{#each boxes as box}
  {@const { width, height } = box}
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{width} * {height} = {width * height}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Box&lt;/span&gt; &lt;span class="na"&gt;box=&lt;/span&gt;&lt;span class="s"&gt;{box}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
{/each}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It takes an extra line, but it means that you don't need to introduce a duplicate object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improving readability
&lt;/h2&gt;

&lt;p&gt;Using &lt;code&gt;@const&lt;/code&gt; can also improve the readability of your code by letting you name a variable for what would otherwise be an inline expression. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Option 1: long, complex inline expression --&amp;gt;&lt;/span&gt;
{#each boxes as box}
  {#if box.width &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt; &lt;span class="err"&gt;30&lt;/span&gt; &lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="na"&gt;box.width&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 10 &lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt; box.height % 3 === 0}
  &lt;span class="c"&gt;&amp;lt;!-- Do some conditional rendering... --&amp;gt;&lt;/span&gt;
  {/if}
{/each}

&lt;span class="c"&gt;&amp;lt;!-- Option 2: extract into a local constant --&amp;gt;&lt;/span&gt;
{#each boxes as box}
  {@const boxFitsTheRoom = box.width &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt; &lt;span class="err"&gt;30&lt;/span&gt; &lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="na"&gt;box.width&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 10 &lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt; box.height % 3 === 0}
  &lt;span class="c"&gt;&amp;lt;!-- The expression is named, which can help
    others understand the purpose of this code --&amp;gt;&lt;/span&gt;
  {#if boxFitsTheRoom}
  &lt;span class="c"&gt;&amp;lt;!-- Do some conditional rendering... --&amp;gt;&lt;/span&gt;
  {/if}
{/each}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While there's no need to do this for &lt;em&gt;every&lt;/em&gt; if statement, it can make your code much more understandable when you have lengthy inline expressions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;The new tag does have a few limitations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Only allowed in certain contexts&lt;/strong&gt;: &lt;code&gt;@const&lt;/code&gt; is only allowed as a direct child of &lt;code&gt;{#each}&lt;/code&gt;, &lt;code&gt;{:then}&lt;/code&gt;, &lt;code&gt;{:catch}&lt;/code&gt;, &lt;code&gt;&amp;lt;Component /&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;svelte:fragment /&amp;gt;&lt;/code&gt;. These are all block types where a new scope is created. You can't use it by itself at the top level of a template or inside an &lt;code&gt;{#if}&lt;/code&gt; / &lt;code&gt;{:else}&lt;/code&gt; block, though the latter does have an &lt;a href="https://github.com/sveltejs/svelte/issues/7241"&gt;open feature request&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Doesn't support non-standard JavaScript:&lt;/strong&gt; because JavaScript expressions inside the markup section of a Svelte component are &lt;a href="https://github.com/sveltejs/svelte/issues/4701"&gt;not preprocessed&lt;/a&gt;, you won't be able to write expressions in a const tag that use non-standard JavaScript (e.g. TypeScript or syntax that requires Babel plugins).&lt;/p&gt;

&lt;p&gt;Also note that at time of writing there are &lt;strong&gt;still some open bugs&lt;/strong&gt; around this feature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fix rvalue error when using arrow functions in {@const} &lt;a href="https://github.com/sveltejs/svelte/issues/7206"&gt;#7206&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;@const declaration inside components ignored &lt;a href="https://github.com/sveltejs/svelte/issues/7189"&gt;#7189&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Unclear error message comes if const is already declared in &amp;lt;script&amp;gt; section &lt;a href="https://github.com/sveltejs/svelte/issues/7221"&gt;#7221&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Object property access in callbacks within @const statements are being treated as separate variables &lt;a href="https://github.com/sveltejs/svelte/issues/7326"&gt;#7326&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;I've already found &lt;code&gt;@const&lt;/code&gt; to be &lt;a href="https://github.com/geoffrich/generative-svg-grid/blob/0e3384cebfd42935f687ce8c69a0e495e19d6a1b/src/lib/Grid.svelte#L45-L57"&gt;very useful&lt;/a&gt; to improve the readability of my code. Keep it in mind next time you're writing Svelte!&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/sveltejs/rfcs/pull/33"&gt;original RFC&lt;/a&gt; is well worth a read for some different perspectives on whether introducing this tag is a good idea or not. It's also interesting in context of RFCs &lt;a href="https://github.com/sveltejs/rfcs/pull/32"&gt;#32&lt;/a&gt; (local &amp;lt;style scoped&amp;gt;) and &lt;a href="https://github.com/sveltejs/rfcs/pull/34"&gt;#34&lt;/a&gt; (inline components). Taken together, these RFCs would allow including multiple components inside a single file. However, at time of writing, only #33 (local constants) has been accepted.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>svelte</category>
    </item>
    <item>
      <title>How to use Svelte's style directive</title>
      <dc:creator>Geoff Rich</dc:creator>
      <pubDate>Mon, 31 Jan 2022 16:50:17 +0000</pubDate>
      <link>https://dev.to/geoffrich/how-to-use-sveltes-style-directive-47l2</link>
      <guid>https://dev.to/geoffrich/how-to-use-sveltes-style-directive-47l2</guid>
      <description>&lt;p&gt;Svelte 3.46 released a new feature: &lt;a href="https://svelte.dev/docs#template-syntax-element-directives-style-property"&gt;style directives&lt;/a&gt;! In this post I'll show you how to use them and the advantages they have over setting the &lt;code&gt;style&lt;/code&gt; attribute directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The style attribute
&lt;/h2&gt;

&lt;p&gt;A common strategy for writing dynamic styles in Svelte is to apply the styles directly as an attribute. For example, here's how you can make a &lt;a href="https://svelte.dev/repl/4c7b90f3872b417f9bbf78cfd4570e8e?version=3.46.3"&gt;box move around&lt;/a&gt; the screen with a couple of range sliders.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;xPos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;yPos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"positionX"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;X &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"positionX"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"range"&lt;/span&gt; &lt;span class="na"&gt;bind:value=&lt;/span&gt;&lt;span class="s"&gt;"{xPos}"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"positionY"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Y &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"positionY"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"range"&lt;/span&gt; &lt;span class="na"&gt;bind:value=&lt;/span&gt;&lt;span class="s"&gt;"{yPos}"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"left: {xPos}%; top: {yPos}%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ({xPos}, {yPos})
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;pink&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key part here is &lt;code&gt;style="left: {xPos}%; top: {yPos}%"&lt;/code&gt; on the div, which takes the &lt;code&gt;xPos&lt;/code&gt; and &lt;code&gt;yPos&lt;/code&gt; state variables and sets the element's styles accordingly.&lt;/p&gt;

&lt;p&gt;This works well, but can get awkward as you add more properties, especially if those properties are conditionally applied. For instance, look at the following example from the &lt;a href="https://github.com/sveltejs/rfcs/blob/master/text/0008-style-directives.md#motivation"&gt;style directive RFC&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
  &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"
    position: {position};
    {position === 'absolute' ? 'top: 20px;' : ''}
    {pointerEvents === false ? 'pointer-events: none;' : ''}
  "&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It would be easy to forget a semicolon or mishandle a ternary statement and break your dynamic styles. Enter: style directives! 🕺&lt;/p&gt;

&lt;h2&gt;
  
  
  Style directives
&lt;/h2&gt;

&lt;p&gt;In Svelte, a &lt;em&gt;style directive&lt;/em&gt; is an attribute applied to an element in the format &lt;code&gt;style:property={value}&lt;/code&gt;, where &lt;em&gt;property&lt;/em&gt; is a CSS property name and &lt;em&gt;value&lt;/em&gt; is the value of that property. By using style directives, you don't need to worry about properly formatting the CSS string, since you set individual properties instead. If you're using Svelte 3.46 or later, the above example can be rewritten like so to use style directives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
  &lt;span class="na"&gt;style:position=&lt;/span&gt;&lt;span class="s"&gt;"absolute"&lt;/span&gt;
  &lt;span class="na"&gt;style:top=&lt;/span&gt;&lt;span class="s"&gt;{position&lt;/span&gt; &lt;span class="err"&gt;===&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;absolute&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="err"&gt;'20&lt;/span&gt;&lt;span class="na"&gt;px&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="na"&gt;:&lt;/span&gt; &lt;span class="na"&gt;null&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;style:pointer-events=&lt;/span&gt;&lt;span class="s"&gt;{pointerEvents&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="na"&gt;null&lt;/span&gt; &lt;span class="na"&gt;:&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;none&lt;/span&gt;&lt;span class="err"&gt;'}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the sliding box example can be written like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt; &lt;span class="na"&gt;style:left=&lt;/span&gt;&lt;span class="s"&gt;"{xPos}%"&lt;/span&gt; &lt;span class="na"&gt;style:top=&lt;/span&gt;&lt;span class="s"&gt;"{yPos}%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ({xPos}, {yPos})
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is about the same amount of code, but is easier to understand and less prone to errors from writing an invalid CSS string.&lt;/p&gt;

&lt;p&gt;You can use style directives with &lt;em&gt;any&lt;/em&gt; CSS property, including CSS custom property definitions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style:--super-cool-custom-property=&lt;/span&gt;&lt;span class="s"&gt;"orange"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's also a shorter syntax available if your variable has the same name as the CSS property you're setting. The below two are equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style:color=&lt;/span&gt;&lt;span class="s"&gt;{color}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style:color&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case when the &lt;code&gt;style&lt;/code&gt; attribute and style directive set the same properties, the style directive will take precedence.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"margin-top: 1rem; color: red"&lt;/span&gt; &lt;span class="na"&gt;style:color=&lt;/span&gt;&lt;span class="s"&gt;"blue"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  I will have 1rem top margin and my color is blue.
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Style optimizations
&lt;/h2&gt;

&lt;p&gt;By using style directives, you also make sure that Svelte will update the element's styles in an optimal way. This was also possible with the &lt;code&gt;style&lt;/code&gt; attribute, but it was easy to accidentally opt-out of the optimization.&lt;/p&gt;

&lt;p&gt;Let's look again at the sliding box example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"left: {xPos}%; top: {yPos}%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ({xPos}, {yPos})
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you compile this component, it turns into two calls to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/setProperty"&gt;setProperty&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;xPos&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;top&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;yPos&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(If you're ever curious what your Svelte component code turns into, the "JS output" tab of the &lt;a href="https://svelte.dev/repl"&gt;REPL&lt;/a&gt; is a great place to start.)&lt;/p&gt;

&lt;p&gt;Svelte performs some clever optimization here and will &lt;em&gt;only&lt;/em&gt; set the property that changes. So, if only &lt;code&gt;xPos&lt;/code&gt; changes, Svelte will only call &lt;code&gt;setProperty('left', xPos + '%')&lt;/code&gt;, and not update &lt;code&gt;top&lt;/code&gt;. This makes the style updates more efficient.&lt;/p&gt;

&lt;p&gt;However, when using the &lt;code&gt;style&lt;/code&gt; attribute, it is easy to accidentally opt-out of this optimization. If you construct the style attribute outside of the template, Svelte can't easily determine how to optimize it and won't try. Instead, it will set the &lt;em&gt;entire style attribute&lt;/em&gt; when either variable is updated. So given this code...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;xPos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;yPos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boxStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`left: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xPos&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%; top: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;yPos&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;{boxStyle}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ({xPos}, {yPos})
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...Svelte won't set &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;top&lt;/code&gt; individually, and instead sets the entire style attribute every time &lt;code&gt;xPos&lt;/code&gt; or &lt;code&gt;yPos&lt;/code&gt; changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;boxStyle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Per &lt;a href="https://github.com/sveltejs/svelte/pull/810"&gt;the original PR&lt;/a&gt; that added this optimization, this will almost always be slower than setting the individual properties. So, it's better to construct the style attribute directly in the template so that Svelte can optimize it.&lt;/p&gt;

&lt;p&gt;However, with style directives, you don't need to think about any of this! Since each style directive corresponds to a single CSS property, it's easy for Svelte to make those same optimizations, even if the value comes from the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;xPos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;yPos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xPos&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;yPos&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- This is optimized the same way as the original example --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt; &lt;span class="na"&gt;style:left&lt;/span&gt; &lt;span class="na"&gt;style:top&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ({xPos}, {yPos})
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using style directives, you make sure that your dynamic styles are applied in an optimized way without needing to think about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;Style directives are great, but they have a few limitations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exclusive to elements:&lt;/strong&gt; Like most Svelte directives (with the exception of &lt;code&gt;on:&lt;/code&gt;), this does not work on components. There is &lt;a href="https://github.com/sveltejs/rfcs/pull/60"&gt;an open RFC&lt;/a&gt; to allow forwarding directives to components, which would include style directives. However, this RFC has not been accepted at time of writing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shorthand only works with dash-less properties:&lt;/strong&gt; Since the property used in the style directive uses the same name as the equivalent CSS property, you can't use the shorthand with properties that contain a dash. This is because you can't use &lt;code&gt;-&lt;/code&gt; in a JavaScript variable (e.g., you can't declare a variable with the name &lt;code&gt;border-color&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- This is valid --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style:border-color=&lt;/span&gt;&lt;span class="s"&gt;{borderColor&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- This is not valid --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style:border-color&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;No camel case:&lt;/strong&gt; Some comments on the original RFC suggested allowing the camel-cased property as well (e.g. &lt;code&gt;style:borderColor&lt;/code&gt;), but that suggestion was not accepted. The &lt;a href="https://github.com/sveltejs/rfcs/pull/42#issuecomment-742110296"&gt;reasoning was&lt;/a&gt; that it's more consistent with the rest of Svelte. For example, you need to do the same with class directives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class:is-active=&lt;/span&gt;&lt;span class="s"&gt;{isActive}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;No style object:&lt;/strong&gt; &lt;a href="https://reactjs.org/docs/dom-elements.html#style"&gt;Unlike React&lt;/a&gt;, you can't pass an object of styles to the style attribute: it needs to be a string. If you do want to do this, it would be fairly simple to &lt;a href="https://github.com/sveltejs/rfcs/pull/42#issuecomment-744560265"&gt;solve in userland&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should you use the style directive for everything?
&lt;/h2&gt;

&lt;p&gt;You shouldn't use style directives for all of your component styles. I would avoid using it if your styles are purely static. For example, there is no need to use style directives on the following component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt; &lt;span class="na"&gt;style:background-color=&lt;/span&gt;&lt;span class="s"&gt;"red"&lt;/span&gt; &lt;span class="na"&gt;style:height=&lt;/span&gt;&lt;span class="s"&gt;"100px"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It would be better to put these styles in the style block of the component instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is better for performance, since everything in &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; is compiled to pure CSS without using any JavaScript to apply the styles. I would only use the style attribute and style directives for styles where the values are changing or are supplied from outside the component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;This feature doesn't enable anything you couldn't do before, but it's a nice bit of syntactic sugar that helps ensure your inline styles are optimized. Go forth and style!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>svelte</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The many meanings of $ in Svelte</title>
      <dc:creator>Geoff Rich</dc:creator>
      <pubDate>Wed, 15 Dec 2021 17:18:16 +0000</pubDate>
      <link>https://dev.to/geoffrich/the-many-meanings-of-in-svelte-1k8l</link>
      <guid>https://dev.to/geoffrich/the-many-meanings-of-in-svelte-1k8l</guid>
      <description>&lt;p&gt;If you're writing Svelte code, you'll notice that &lt;code&gt;$&lt;/code&gt; can have multiple different meanings, depending on the context. For example, look at this code snippet — &lt;code&gt;$&lt;/code&gt; is used in three different ways! If you're new to Svelte, or to JavaScript in general, it can be confusing to keep them all straight.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Total: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;$count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this post, I'll show all the different meanings that &lt;code&gt;$&lt;/code&gt; can have in Svelte.&lt;/p&gt;

&lt;p&gt;First, let's start with the primary uses of &lt;code&gt;$&lt;/code&gt; in Svelte: reactive statements and reactive stores.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reactive statements
&lt;/h2&gt;

&lt;p&gt;In a Svelte component, prefixing a statement with &lt;code&gt;$:&lt;/code&gt; marks the statement as &lt;em&gt;reactive&lt;/em&gt; — it will run whenever the variables referenced in that statement change. Here's a classic example. Whenever &lt;code&gt;num&lt;/code&gt; changes, &lt;code&gt;doubled&lt;/code&gt; is automatically set to the correct value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doubled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Num: {num}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Doubled: {doubled}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; num++}&amp;gt;
    Increment
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's also possible to have an entire reactive block that runs when the variables referenced inside it change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;doubled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;doubled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;doubled&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a core concept of Svelte. If you're not familiar with it, go review the section of the Svelte tutorial on &lt;a href="https://svelte.dev/tutorial/reactive-declarations"&gt;reactivity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is valid JavaScript, since it uses the obscure &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label"&gt;label&lt;/a&gt; syntax. However, its reactive properties are unique to Svelte, and specifically to Svelte components. Using this syntax inside a regular &lt;code&gt;.js&lt;/code&gt; file will not make a statement reactive.&lt;/p&gt;

&lt;p&gt;Since this is a valid label, you can exit a reactive block early the same way you'd &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label#using_a_labeled_break_statement"&gt;break out of a regular label&lt;/a&gt;. This example will keep track of the number of evens, but only until the counter reaches 10. At that point, &lt;code&gt;break $&lt;/code&gt; will exit the block early.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;evens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;evens&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; (counter++)}&amp;gt;
    Increment
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    Counter: {counter}, evens before 10: {evens}
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You won't need to use this very often, but it's useful to know about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessing store values
&lt;/h2&gt;

&lt;p&gt;The other primary use of &lt;code&gt;$&lt;/code&gt; you'll see in a Svelte component is when referencing the current value of a store. In Svelte, a &lt;a href="https://svelte.dev/tutorial/writable-stores"&gt;store&lt;/a&gt; is any object with a &lt;code&gt;subscribe&lt;/code&gt; method that allows you to be notified when the value of the store changes. It's especially useful when you want a reactive value to be accessible from muliple components in your application, since the store can live outside of a Svelte component.&lt;/p&gt;

&lt;p&gt;If you wanted to get the current value of a store in a Svelte component and have it automatically update when the store changes, you could do something like the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./count&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onDestroy&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;_count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;onDestroy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code subscribes to the &lt;code&gt;count&lt;/code&gt; store, updates the local &lt;code&gt;_count&lt;/code&gt; variable when the store changes, and unsubscribe from the store when the component is destroyed. However, this is a lot of boilerplate.&lt;/p&gt;

&lt;p&gt;Thankfully, Svelte has a special syntax to make this sort of thing easy. Inside a Svelte component, we can reference the current value of the &lt;code&gt;count&lt;/code&gt; store with the variable &lt;code&gt;$count&lt;/code&gt;. By using this syntax, Svelte will take care of subscribing and unsubscribing to the store for us.&lt;/p&gt;

&lt;p&gt;As with reactive declarations, this syntax only works inside a Svelte component. In regular JS files, you'll need to subscribe to the store manually.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparing reactive statements and reactive stores
&lt;/h3&gt;

&lt;p&gt;Those are the two primary ways &lt;code&gt;$&lt;/code&gt; is used inside Svelte. If the dollar sign has a colon after it (&lt;code&gt;$:&lt;/code&gt;), then it indicates a &lt;a href="https://svelte.dev/docs#3_%24_marks_a_statement_as_reactive"&gt;reactive statement&lt;/a&gt;. If it is at the start of a variable name inside a Svelte component, then it's &lt;a href="https://svelte.dev/docs#4_Prefix_stores_with_%24_to_access_their_values"&gt;accessing a reactive store value&lt;/a&gt;. In general, when you see &lt;code&gt;$&lt;/code&gt; in a Svelte component, you should think &lt;em&gt;reactivity&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Note that there are often times where you'll want to combine the two. Referencing a store value in the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; block with &lt;code&gt;$&lt;/code&gt; does &lt;em&gt;not&lt;/em&gt; mean that value will automatically be updated when the store changes. In the following example, &lt;code&gt;doubledCount&lt;/code&gt; will not be automatically updated unless you mark that assignment as reactive with &lt;code&gt;$:&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// count is a store&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./count&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// doesn't keep value updated&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;doubledCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// keeps value updated&lt;/span&gt;
    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doubledCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This could seem unintuitive — didn't I just say that a store is reactive? Yes, but it's only reactive in that &lt;em&gt;we can be notified any time the value changes&lt;/em&gt;. If we want to derive a value from it, we still need to mark that statement as reactive as well.&lt;/p&gt;

&lt;p&gt;This is a little difficult to wrap your head around, so see this alternate explanation in &lt;a href="https://www.reddit.com/r/sveltejs/comments/r6j9r4/i_still_dont_get_this_and_need_an_eli5/hmy13ud/"&gt;r/sveltejs&lt;/a&gt; if you're still having trouble.&lt;/p&gt;

&lt;p&gt;However, those are not the only times you'll see &lt;code&gt;$&lt;/code&gt; in a Svelte component. &lt;code&gt;$&lt;/code&gt; is used in other ways, both in Svelte and in vanilla JavaScript in general. Let's go over a few more examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Template literals
&lt;/h2&gt;

&lt;p&gt;This is not Svelte-specific, but is worth mentioning, since it's a common technique in modern JavaScript. When writing &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;template literals&lt;/a&gt; in JavaScript, you can use &lt;code&gt;${var}&lt;/code&gt; to insert the value of a variable into the template string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;running&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;walking&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// both output "running and walking"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; and &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// without template literals&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; and &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// with template literals&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where this could get confusing is if you combine template literals with reactive statements and stores! Make sure you can pick out what each &lt;code&gt;$&lt;/code&gt; means in the below example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`num is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; and the store is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;$count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  $$props, $$restProps, and $$slots
&lt;/h2&gt;

&lt;p&gt;These are globally-available variables inside a Svelte component. &lt;code&gt;$$props&lt;/code&gt; contains all the props passed to the component, &lt;code&gt;$$restProps&lt;/code&gt; contains all the props that were not explicitly exported by the component (which useful for wrapping native HTML elements like &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;), and &lt;code&gt;$$slots&lt;/code&gt; contains the slots passed to the component. Here, \$\$ doesn't indicate that this is a store value; it's just a naming convention.&lt;/p&gt;

&lt;p&gt;In fact, their naming mirrors how Svelte names things internally. For example, if you look at the code Svelte generates, you'll see reference to similarly-named variables like &lt;code&gt;$$self&lt;/code&gt; and &lt;code&gt;$$invalidate&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$$self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$$props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$$invalidate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;click_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;$$invalidate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;click_handler&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://svelte.dev/docs#Client-side_component_API"&gt;client-side component API&lt;/a&gt; also prefixes its methods with &lt;code&gt;$&lt;/code&gt; to avoid colliding with methods defined on the component instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a derived store
&lt;/h2&gt;

&lt;p&gt;When creating a &lt;a href="https://svelte.dev/docs#derived"&gt;derived store&lt;/a&gt;, it is common to prefix the values of the store in the derived callback with &lt;code&gt;$&lt;/code&gt;. You'll see this in the derived store examples in the Svelte docs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;derived&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doubled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;derived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not required and does not indicate anything special — it works the same in and out of Svelte components. It just provides an easy way to distinguish the variable in the callback (which has the updated value of the store) and the reference to the store itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;While it might seem difficult to keep track of all these at first, given enough experience you'll get the hang of it. It's most important to understand the difference between the first three examples. You're less likely to encounter the others until you reach more advanced scenarios.&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Svelte's lifecycle methods can be used anywhere</title>
      <dc:creator>Geoff Rich</dc:creator>
      <pubDate>Tue, 30 Nov 2021 17:19:44 +0000</pubDate>
      <link>https://dev.to/geoffrich/sveltes-lifecycle-methods-can-be-used-anywhere-4e77</link>
      <guid>https://dev.to/geoffrich/sveltes-lifecycle-methods-can-be-used-anywhere-4e77</guid>
      <description>&lt;p&gt;I don't think it's widely known that you can call the Svelte lifecycle methods (onMount, onDestroy, beforeUpdate, afterUpdate) &lt;em&gt;outside&lt;/em&gt; of a component. It is mentioned in the &lt;a href="https://svelte.dev/docs#onMount"&gt;Svelte docs&lt;/a&gt; and tutorial, though it's easy to gloss over.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;onMount&lt;/code&gt; function schedules a callback to run as soon as the component has been mounted to the DOM. It must be called during the component's initialisation (but doesn't need to live &lt;em&gt;inside&lt;/em&gt; the component; it can be called from an external module).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;onMount&lt;/code&gt; and friends are &lt;a href="https://github.com/sveltejs/svelte/blob/6ff1aed8d5051ef79063e8d6442d8b6d6def63a2/src/runtime/internal/lifecycle.ts#L14-L28"&gt;just functions&lt;/a&gt; that schedule another function to run during a point in the current component's lifecycle. As long as you call these functions during a component's initialization, you can call them from anywhere. This means you can share lifecycle-dependent functionality between multiple components by putting it in a separate file, making it more reusable and reducing boilerplate.&lt;/p&gt;

&lt;p&gt;Let's look at a few examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running a callback after a given interval
&lt;/h2&gt;

&lt;p&gt;You can write the following Svelte code to start a timer that tracks how long the page has been open. We wrap the &lt;code&gt;setInterval&lt;/code&gt; call inside &lt;code&gt;onMount&lt;/code&gt; so that it only runs in the browser, and not when the component is being server-rendered.&lt;/p&gt;

&lt;p&gt;By returning a cleanup function from &lt;code&gt;onMount&lt;/code&gt;, we tell Svelte to run that function when the component is being destroyed. This prevents a memory leak.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
  This page has been open {count} seconds.
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what if you want to use this code in multiple components? You may have thought that because this code uses a component lifecycle method that it has to stay with the component. However, that's not the case. We can move this code to a separate module, as long as the function calling &lt;code&gt;onMount&lt;/code&gt; is called when the component is initializing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// interval.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;onInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onInterval&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./interval.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;onInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
  This page has been open {count} seconds.
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have the same behavior, but now it can be reused across multiple components! You can find a similar example using &lt;code&gt;onDestroy&lt;/code&gt; instead in the &lt;a href="https://svelte.dev/tutorial/ondestroy"&gt;Svelte tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A store that tells you if a component has been mounted
&lt;/h2&gt;

&lt;p&gt;We can also use &lt;code&gt;onMount&lt;/code&gt; to make a store that tells you whether a component has finished mounting or not. This code is from the &lt;a href="https://github.com/ghostdevv/svelte-mount"&gt;svelte-mount&lt;/a&gt; package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mounted.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mounted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I found this a little hard to parse at first, but what we have here is a &lt;strong&gt;custom store&lt;/strong&gt;. Per the &lt;a href="https://svelte.dev/docs#Store_contract"&gt;Svelte docs&lt;/a&gt;, a store is any object with a subscribe method that takes a subscription function. When a component subscribes to this store, the subscription function is first called with &lt;code&gt;false&lt;/code&gt; . We then wrap a call to the subscription function in &lt;code&gt;onMount&lt;/code&gt; so that it is set to true once the component is mounted.&lt;/p&gt;

&lt;p&gt;Because this code is in the &lt;code&gt;subscribe&lt;/code&gt; function, it will run for each component that subscribes to the store, meaning that &lt;code&gt;onMount&lt;/code&gt; will refer to a different component's lifecycle each time it's called.&lt;/p&gt;

&lt;p&gt;Here's an example of where this store would be useful. Normally, transitions don't play on initial render, so by adding the element after &lt;code&gt;onMount&lt;/code&gt; has completed we allow the transition to play. By using the &lt;code&gt;mounted&lt;/code&gt; store, we remove some boilerplate — we don't have to make a state variable to track if the component has mounted and update it in &lt;code&gt;onMount&lt;/code&gt;. Nifty!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./mounted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fade&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/transition&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;
  Hello world
&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
{#if $mounted}
&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;in:fade&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Component has been mounted.
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{/if}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also set the &lt;code&gt;intro&lt;/code&gt; property when &lt;a href="https://svelte.dev/docs#Creating_a_component"&gt;creating the component&lt;/a&gt; to force transitions to play on initial render, though that won't work in a server-rendered context like SvelteKit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Track the number of times a component is rendered
&lt;/h2&gt;

&lt;p&gt;This example is a bit contrived, but still interesting. Someone asked a question on &lt;a href="https://www.reddit.com/r/sveltejs/comments/q8hj8k/how_to_extract_crosscutting_concerns_in_svelte/"&gt;r/sveltejs&lt;/a&gt; about how to track how many times a component has re-rendered in a way that can be shared across multiple components. They gave the following React hook as an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useRenderCount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// used in a component like so&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRenderCount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many folks suggested using the &lt;a href="https://svelte.dev/docs#afterUpdate"&gt;afterUpdate&lt;/a&gt; Svelte lifecycle method inside the component, but didn't realize that it could be moved outside the component as well. We can re-create this behavior completely independent from the component by combining &lt;code&gt;afterUpdate&lt;/code&gt; with a writable Svelte store.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;afterUpdate&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;trackUpdateCount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;afterUpdate&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it can be used like so, without needing to add any lifecycle boilerplate to the component itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- Input.svelte --&amp;gt;
&amp;lt;script&amp;gt;
  export let name = 'test';

  import trackUpdateCountfrom './trackUpdateCount';
  const count = trackUpdateCount();
&amp;lt;/script&amp;gt;

&amp;lt;p&amp;gt;Hello {name}! Updated {$count} times&amp;lt;/p&amp;gt;
&amp;lt;input bind:value="{name}" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a &lt;a href="https://svelte.dev/repl/7a88abc02a444e44b80682ca8c32ef63?version=3.43.2"&gt;REPL&lt;/a&gt; if you want to try it out.&lt;/p&gt;

&lt;p&gt;I haven't quite wrapped my mind around it, but you can even use &lt;code&gt;afterUpdate&lt;/code&gt; in Svelte to replicate React's useEffect hook. See this &lt;a href="https://svelte.dev/repl/0c9cd8c29c5043eea89bd9c6eb4f279a?version=3.42.6"&gt;example from Rich Harris&lt;/a&gt;, which I found in an interesting &lt;a href="https://github.com/sveltejs/svelte/issues/6730"&gt;GitHub issue&lt;/a&gt; discussing the edges of Svelte's reactivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleaning up subscriptions
&lt;/h2&gt;

&lt;p&gt;Another common use of lifecycle methods is to clean up store subscriptions. When you use Svelte's special &lt;code&gt;$store&lt;/code&gt; syntax inside a component, Svelte automatically subscribes to the store and unsubscribes when the component is destroyed. However, if you subscribe to a store in a regular JavaScript file, you need to unsubscribe manually. This is a great opportunity to use &lt;code&gt;onDestroy&lt;/code&gt; — that way, a single file can handle the cleanup instead of requiring the importing components to do it.&lt;/p&gt;

&lt;p&gt;At a high level, it could look something like this. Note that this is in an external file, &lt;em&gt;not&lt;/em&gt; a Svelte component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// store.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onDestroy&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsubscribeItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$items&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do something when items changes&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// we clean up the subscription ourselves,&lt;/span&gt;
  &lt;span class="c1"&gt;// instead of making the component do it&lt;/span&gt;
  &lt;span class="nx"&gt;onDestroy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;unsubscribeItems&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then call this function to initialize the store in a component, and the subscription from this file will be automatically cleaned up when the component is destroyed.&lt;/p&gt;

&lt;p&gt;For a more concrete example, take a look at this function. We return two stores, &lt;code&gt;items&lt;/code&gt; and &lt;code&gt;selected&lt;/code&gt;. The &lt;code&gt;selected&lt;/code&gt; store is used to track which items are selected, and is generally controlled by the consuming component. However, when items changes, we want to do one of two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If all items were selected, all items should still be selected (regardless of any overlap)&lt;/li&gt;
&lt;li&gt;If a subset of items were selected, we should keep any common items selected. So if &lt;code&gt;selected&lt;/code&gt; was &lt;code&gt;[2,3]&lt;/code&gt; and the new items are &lt;code&gt;[2,4,6]&lt;/code&gt;, then we should update selected to be &lt;code&gt;[2]&lt;/code&gt; .&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's what the function looks like, and a &lt;a href="https://svelte.dev/repl/ca0cc9c7ae284101a2676d830bc511ad?version=3.44.2"&gt;REPL&lt;/a&gt; to demo how it's used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onDestroy&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createSelectedStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialItems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialItems&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;oldItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialItems&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsubscribeItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$items&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_selected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;_selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// if all items were selected, select all of the new items&lt;/span&gt;
      &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// otherwise, only select items that are shared between the old and new set&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commonItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;_selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commonItems&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;oldItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;onDestroy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;unsubscribeItems&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;selected&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because we subscribe to the items store so that we can update the selected store, we need to unsubscribe from it in &lt;code&gt;onDestroy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In practice, I used a store like this in &lt;a href="https://marvel.geoffrich.net/year/1984"&gt;my site to filter Marvel comics&lt;/a&gt; released in a given year. For each year, users can filter the list of comics for different creators (e.g. only view comics by Chris Claremont). When changing from one year to the next, I want to preserve the filter state as outlined above — if the creators for the next year contain creators that were selected from the previous year, those creators should stay selected.&lt;/p&gt;

&lt;p&gt;I simplified my implementation of this for the above example, but you can find the original code &lt;a href="https://github.com/geoffrich/marvel-by-year/blob/9bf6c252a68dec46d49f37fff215806823c5617e/src/lib/stores/selected.ts"&gt;on GitHub.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;You won't run into this use case commonly, and not every example I showed needs to be done this way. For some of these examples, you can get a similar outcome using a store. However, it's good to keep this technique in mind for when it becomes necessary.&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to make your Svelte transitions more accessible</title>
      <dc:creator>Geoff Rich</dc:creator>
      <pubDate>Wed, 24 Nov 2021 16:40:50 +0000</pubDate>
      <link>https://dev.to/geoffrich/how-to-make-your-svelte-transitions-more-accessible-4112</link>
      <guid>https://dev.to/geoffrich/how-to-make-your-svelte-transitions-more-accessible-4112</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/iceNAO8c4J4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I gave a talk at last weekend's Svelte Summit on transitions and accessibility. Svelte includes built-in animations that makes it easy to slide, scale, and fly elements in and out of the DOM. However, you need to be careful to not trigger motion sickness in your users. In my talk, I go over which Svelte transitions could cause accessibility issues and how to respect user motion preferences when using them.&lt;/p&gt;

&lt;p&gt;We iteratively build a solution to change which transition we use when the user requests reduced motion -- first only using CSS, then detecting the user's motion preference in a Svelte component, to finally encapsulating the logic in a reusable Svelte store.&lt;/p&gt;

&lt;p&gt;Following is a full transcript of the talk. You can find my &lt;a href="https://docs.google.com/presentation/d/1djta1tNkYdN7B287S3U9Stfo0L8q0lfgsVQGUKBu2N4/edit?usp=sharing"&gt;slide deck&lt;/a&gt; on Google Slides and the &lt;a href="https://github.com/geoffrich/svelte-summit-accessible-transitions"&gt;example code&lt;/a&gt; on my GitHub. The rest of the event is available to stream on &lt;a href="https://youtu.be/1Df-9EKvZr0"&gt;YouTube&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Huge shout-out to the organizers for putting on such a great event and for featuring my talk! Special thanks to Kevin for being very quick to respond to my questions via email, and to Shawn (a.k.a. swyx) for hosting a speaker prep session with some very helpful tips.&lt;/p&gt;




&lt;p&gt;Hi, I'm Geoff. I'm a software engineer at Alaska Airlines and today I want to talk about Svelte transitions.&lt;/p&gt;

&lt;p&gt;Svelte transitions are amazing! I love that with only a few lines of code and no additional dependencies, you can add some animation that can really make your app stand out. However, you need to be careful. Some people are sensitive to motion. If you use these transitions irresponsibly, they can trigger headaches, dizziness, and even nausea—and this is not how people should feel when they visit your website!&lt;/p&gt;

&lt;p&gt;Remember — to quote the &lt;a href="https://svelte.dev/tutorial/custom-css-transitions"&gt;official Svelte transition tutorial&lt;/a&gt;, "with great power comes great responsibility."&lt;/p&gt;

&lt;p&gt;In this talk, I'll talk about the types of animation that can cause accessibility issues, how to detect if the user has requested reduced motion, and how to apply these concepts to Svelte transitions&lt;/p&gt;

&lt;h2&gt;
  
  
  Motion and accessibility
&lt;/h2&gt;

&lt;p&gt;First, let's talk about motion and accessibility.&lt;/p&gt;

&lt;p&gt;So, who does this affect? Well, the largest group affected by animation on the web is people with vestibular disorders. The vestibular system controls your body's sense of balance. If it doesn't function properly, you could experience dizziness, loss of balance, and vertigo, among other symptoms. And animation can often be a trigger for these effects.&lt;/p&gt;

&lt;p&gt;According to the National Institute on Deafness and Other Communication Disorders, 4% of American adults report a chronic problem with balance. That's millions of people, many of whom could be using your website or app.&lt;/p&gt;

&lt;p&gt;So what kinds of animation can cause issues? Well, there are a few factors.&lt;/p&gt;

&lt;p&gt;In general, you want to avoid large amounts of movement. So a button moving a few pixels when you hover it is okay, but something flying across the entire screen could cause an issue. You also want to be careful with multiple elements moving at the same time, especially if they're moving in different directions or at different speeds, such as parallax type movement. And tying any movement to the user's scroll position could be problematic, especially if the element is moving at a different speed or direction from how the user is scrolling.&lt;/p&gt;

&lt;p&gt;I recommend the A List Apart article &lt;a href="https://alistapart.com/article/designing-safer-web-animation-for-motion-sensitivity/"&gt;"Designing Safer Web Animation for Motion Sensitivity"&lt;/a&gt; from Val Head if you want more detail on this.&lt;/p&gt;

&lt;p&gt;So with that in mind, what Svelte transitions deserve extra caution? Well, of the 7 built-in Svelte transitions, 5 of them involve motion. Those would be fly, slide, scale, draw, and crossfade. Transitions like fade and blur that do &lt;em&gt;not&lt;/em&gt; involve motion are unlikely to cause issues. This doesn't mean that all uses of these transitions are problematic. What you should look out for is the amount and direction of the motion.&lt;/p&gt;

&lt;p&gt;So does that mean if you care about accessibility, you're not allowed to use these transitions? Of course not! But you should provide an alternate experience for users who are sensitive to motion. And that's where prefers-reduced-motion comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prefers reduced motion
&lt;/h2&gt;

&lt;p&gt;So, Operating systems have started to add ways for users to request reduced motion. [slides show image of iOS and Mac accessibility settings] Here is where you can find it on iOS and Mac, where it's called "reduce motion". [slides show Windows settings and Chrome DevTools] And here's where it is on Windows, under "show animations in Windows". Chrome also lets you set it directly in DevTools, so you can emulate that experience without having to adjust your OS settings.&lt;/p&gt;

&lt;p&gt;Here's a video of how iOS behaves when you have this setting enabled. Motion warning for the next few seconds. Normally, opening an app triggers a zooming animation where the app expands into view. However, if you turn on this setting [reduced motion], apps fade in and out instead.&lt;/p&gt;

&lt;p&gt;Originally this setting was just for users to control their operating system, but it's also available as a media query in web browsers, and it has great browser support. So, we can detect if a user has requested reduced motion, and adjust our site accordingly.&lt;/p&gt;

&lt;p&gt;So let's recap. We know that large amounts of motion can trigger dizziness and nausea in some of our users. We have a media query that can detect if they've requested reduced motion. But how do we apply that to transitions in our Svelte application? Well, there's a few different options. Enough slides. Let’s jump to some code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Live demo
&lt;/h2&gt;

&lt;p&gt;First, let me show you where we're starting. We have a checkbox here that will hide and show this box. The box has a fly transition applied, so that it flies in and out. I set the y parameter very low to minimize any triggering motion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fly&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/transition&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;show&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"show"&lt;/span&gt; &lt;span class="na"&gt;bind:checked=&lt;/span&gt;&lt;span class="s"&gt;{show}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"show"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Show box&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{#if show}
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt; &lt;span class="na"&gt;transition:fly=&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;y:&lt;/span&gt; &lt;span class="err"&gt;30&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"emoji"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;📦&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{/if}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what the transition looks like with reduced motion disabled. [box flies in and out]&lt;/p&gt;

&lt;p&gt;So, the first way to respect reduced motion is to disable all animation entirely. Svelte's built-in transitions are applied using native CSS animations, so this snippet will prevent those animations from playing if reduced motion is turned on. Because Svelte's transitions use inline styles, we need to use &lt;code&gt;!important&lt;/code&gt; here so that this override applies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;animation-duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.01ms&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;animation-iteration-count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition-duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.01ms&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;animation-delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.01ms&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, this seems to work. If I enable prefers-reduced motion in Chrome, then the fly animation doesn't play. Is that all there is to it? Well, this approach has some drawbacks.&lt;/p&gt;

&lt;p&gt;It's definitely better than not respecting motion preference at all. However, we use animation for a reason. Animation is often essential to make your interface understandable. So we don't want to turn it off entirely.&lt;/p&gt;

&lt;p&gt;Remember: it's prefers &lt;em&gt;reduced&lt;/em&gt; motion, not prefers &lt;em&gt;no&lt;/em&gt; motion.&lt;/p&gt;

&lt;p&gt;Instead, we could behave more like iOS does—if reduced motion is requested, change the animation we use to have less motion. On iOS, they change the zoom to a fade instead when an app opens. We could do the same — fade the element in instead of flying it in.&lt;/p&gt;

&lt;p&gt;Of course, this approach requires more vigilance on the part of the developer. You need to be intentional when implementing animation and choose what the fallback should be for users with motion sensitivities. But, this approach will result in a richer experience for those users as well.&lt;/p&gt;

&lt;p&gt;Even if you do choose to globally disable animation like this, remember that some Svelte animations are applied purely through JavaScript, not CSS. Custom JavaScript transitions and animation using the spring or tweened stores won't be affected by a CSS-only solution. So, it's worthwhile to consider other methods as well.&lt;/p&gt;

&lt;p&gt;Now, let's look at how we can detect reduced motion in JavaScript, and change the transition we use accordingly.&lt;/p&gt;

&lt;p&gt;This is the same component as before, except now the transition we use is stored in a variable. &lt;code&gt;transitionToUse&lt;/code&gt; will reactively update based on the value of &lt;code&gt;reducedMotion&lt;/code&gt;. If reduced motion is true, we'll use the fade transition. Otherwise, we'll use the fly transition. But for that to work, we need to set &lt;code&gt;reducedMotion&lt;/code&gt; properly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fly&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/transition&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;show&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;reducedMotion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;transitionToUse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reducedMotion&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;fade&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fly&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"show"&lt;/span&gt; &lt;span class="na"&gt;bind:checked=&lt;/span&gt;&lt;span class="s"&gt;{show}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"show"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Show box&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{#if show}
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt; &lt;span class="na"&gt;transition:transitionToUse=&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;y:&lt;/span&gt; &lt;span class="err"&gt;30&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"emoji"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;🐱&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{/if}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we'll call &lt;code&gt;window.matchMedia&lt;/code&gt; to get a media query list that will tell us if the reduced motion media query applies. We can also add an event listener to this list, so that if the user changes their motion preference, we can immediately react to it instead of only checking on initial load. And just like any time when we add an event listener manually, we need to remove it when the component is destroyed. Finally, if you're doing this in a server-side rendering context like SvelteKit, you need to make sure we're in the browser so that we can use a function from the window.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fly&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fade&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/transition&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onDestroy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$app/env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;show&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;reducedMotion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;transitionToUse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reducedMotion&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;fade&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fly&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducedMotionQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(prefers-reduced-motion: reduce)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mediaQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducedMotionQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;reducedMotion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mediaQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setReducedMotion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;reducedMotion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="nx"&gt;mediaQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setReducedMotion&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;onDestroy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;mediaQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setReducedMotion&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"show"&lt;/span&gt; &lt;span class="na"&gt;bind:checked=&lt;/span&gt;&lt;span class="s"&gt;{show}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"show"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Show box&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{#if show}
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt; &lt;span class="na"&gt;transition:transitionToUse=&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;y:&lt;/span&gt; &lt;span class="err"&gt;30&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"emoji"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;🐱&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{/if}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's all there is to it! When we set prefers reduced motion, the box now fades in. After we unset it, the box flies in.&lt;/p&gt;

&lt;p&gt;So this works great — now let's make it more reusable. Stores are a great way to extract reactive logic in Svelte. I've updated this example to use a store instead of a local variable, but we still need to implement it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fly&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fade&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/transition&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;reducedMotion&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$lib/reducedMotionStore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;show&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;transitionToUse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$reducedMotion&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;fade&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fly&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"show"&lt;/span&gt; &lt;span class="na"&gt;bind:checked=&lt;/span&gt;&lt;span class="s"&gt;{show}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"show"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Show box&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{#if show}
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt; &lt;span class="na"&gt;transition:transitionToUse=&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;y:&lt;/span&gt; &lt;span class="err"&gt;30&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"emoji"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;🐶&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{/if}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we'll get the initial value of the store using the query from before, defaulting to false if we're not in the browser. Then, we'll pass a function as the second argument to the store. This function will be called when the store gets its first subscriber, so it's a great place to set up event listeners. We'll add the listener from before to react to preference changes. We can return a cleanup function to remove the event listener when there are no more subscribers. And just like before, we only want to run this code in the browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;readable&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$app/env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducedMotionQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(prefers-reduced-motion: reduce)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getInitialMotionPreference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducedMotionQuery&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;readable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getInitialMotionPreference&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setReducedMotion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducedMotionQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setReducedMotion&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;mediaQueryList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setReducedMotion&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you have it — a reactive, reusable store to detect the user's motion preference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Could Svelte make this easier?
&lt;/h2&gt;

&lt;p&gt;So, writing all this code begs the question: could Svelte make any of this easier? And my answer is: maybe! At minimum, I think it would be good to document the need to respect motion preferences when using Svelte transitions.&lt;/p&gt;

&lt;p&gt;However, I think it's tricky to figure out just how much of what I just showed could or should be integrated into Svelte itself. For instance, I wouldn't want to add that animation-disabling CSS snippet into the template and call it a day. As I talked about earlier, there's a lot more nuance involved there. At its core, this is a design question, and there isn't going to be an answer that's the same for every app. But maybe there's a way to make it easier to adjust animation based on motion preference, by adding similar code to what I showed you.&lt;/p&gt;

&lt;p&gt;There is an open &lt;a href="https://github.com/sveltejs/svelte/issues/5346"&gt;GitHub issue&lt;/a&gt; around this already. If you have thoughts or suggestions as to how to make this sort of thing easier, go comment over there. But at the end of the day, it’s our responsibility to make sure the code we write is accessible. Anything Svelte does won't change that.&lt;/p&gt;

&lt;p&gt;Thanks for watching. If you want to learn more, here are some resources I found helpful while preparing for this talk, by designers and developers much more knowledgeable about this than I am. At the bottom are two articles I wrote on my personal blog about this topic earlier this year. They formed the foundation for this talk.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smashing Magazine, &lt;a href="https://www.smashingmagazine.com/2021/10/respecting-users-motion-preferences/"&gt;“Respecting Users’ Motion Preferences”&lt;/a&gt; and &lt;a href="https://www.smashingmagazine.com/2020/09/design-reduced-motion-sensitivities/"&gt;“Designing With Reduced Motion for Motion Sensitivities”&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;CSS-Tricks, &lt;a href="https://css-tricks.com/revisiting-prefers-reduced-motion-the-reduced-motion-media-query/"&gt;“Revisiting prefers-reduced-motion, the reduced motion media query”&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;web.dev, &lt;a href="https://web.dev/prefers-reduced-motion/"&gt;“prefers-reduced-motion: Sometimes less movement is more”&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;geoffrich.net, &lt;a href="https://geoffrich.net/posts/svelte-prefers-reduced-motion-store/"&gt;“A Svelte store for prefers-reduced-motion”&lt;/a&gt;
and &lt;a href="https://geoffrich.net/posts/accessible-svelte-transitions/"&gt;“Accessible Svelte Transitions”&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find me on Twitter &lt;a href="https://twitter.com/geoffrich_"&gt;@geoffrich_&lt;/a&gt;, or at my personal site, &lt;a href="https://geoffrich.net/"&gt;geoffrich.net&lt;/a&gt;, where I regularly write about Svelte. If you have any questions, feel free to reach out on Twitter. Thanks again!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@nathananderson?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Nathan Anderson&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/fall-mountain?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>a11y</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What Svelte's accessibility warnings won't tell you</title>
      <dc:creator>Geoff Rich</dc:creator>
      <pubDate>Wed, 20 Oct 2021 20:15:32 +0000</pubDate>
      <link>https://dev.to/geoffrich/what-sveltes-accessibility-warnings-wont-tell-you-5amk</link>
      <guid>https://dev.to/geoffrich/what-sveltes-accessibility-warnings-wont-tell-you-5amk</guid>
      <description>&lt;p&gt;Svelte's accessibility (often shortened to "a11y") warnings are one of the framework's standout features. Per &lt;a href="https://twitter.com/rich_harris/status/1008856270084898816"&gt;Rich Harris&lt;/a&gt;, Svelte is an "a11y-first framework" that "will &lt;em&gt;let&lt;/em&gt; you write non-accessible markup, but it won't respect you for it." Accessibility warnings in the compiler have been a part of the framework &lt;a href="https://github.com/sveltejs/svelte/issues/374"&gt;since version 1.38&lt;/a&gt;, and are highlighted in the &lt;a href="https://svelte.dev/tutorial/dynamic-attributes"&gt;first section&lt;/a&gt; of the tutorial.&lt;/p&gt;

&lt;p&gt;When I was first learning about Svelte, I was intrigued by this feature. However, I couldn't find much discussion on what these warnings include. Most mentions of this feature only give image alt text as example—certainly important, but only a small part of making an accessible web page. Also, until recently, there wasn't much mention of accessibility in the Svelte docs, though now there's a list of the &lt;a href="https://svelte.dev/docs#Accessibility_warnings"&gt;compiler a11y warnings&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this post I will answer a few questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do frameworks make for less accessible sites?&lt;/li&gt;
&lt;li&gt;Just how effective are Svelte's a11y warnings?&lt;/li&gt;
&lt;li&gt;What won't they warn you about?&lt;/li&gt;
&lt;li&gt;How could Svelte improve?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The curse of React
&lt;/h2&gt;

&lt;p&gt;Yes, in an article about Svelte I'm starting off by talking about React. Bear with me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[React] has greatly simplified the building of complex interactions so everybody rolls their own--but they don't realize they've messed up the accessibility of their apps.&lt;/p&gt;

&lt;p&gt;— &lt;a href="https://twitter.com/ryanflorence/status/1095853086478761984?s=20"&gt;Ryan Florence&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;a href="https://www.youtube.com/watch?v=orq9XnHGTgQ"&gt;Curse of React&lt;/a&gt; is that the average React app is &lt;em&gt;less&lt;/em&gt; accessible than the average jQuery app. This is because React simplified building UI to the point that developers write their own complex UI components instead of using a standard library like jQuery UI. However, the average developer doesn't know everything that's needed to make something like an autocomplete accessible, resulting in less accessible components.&lt;/p&gt;

&lt;p&gt;This curse isn't unique to React—at this point, the Curse of React is really the curse of UI frameworks in general, including Svelte. Since Svelte is still a developing ecosystem, it suffers even more from the Curse of React. There aren't a lot of options for Svelte component libraries, let alone accessible ones. And because React is still the biggest framework, the best thinkers in accessibility are focusing on that ecosystem (e.g. &lt;a href="https://react-spectrum.adobe.com/react-aria/"&gt;React ARIA&lt;/a&gt;, &lt;a href="https://www.downshift-js.com/"&gt;Downshift&lt;/a&gt;, and others).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I hesitated to mention this last point because it technically has to do with adoption, but I cannot separate it from React's merits: it seems to have the best thinkers on accessibility and interaction design right now. No other ecosystem has projects like Adobe and Devon Govett's React Aria that has extensively thought through and tested for WAI-ARIA so you don't have to. Ditto Segun Adebayo's Chakra UI.&lt;/p&gt;

&lt;p&gt;—Swyx, &lt;a href="https://dev.to/swyx/svelte-for-sites-react-for-apps-2o8h"&gt;Svelte for Sites, React for Apps&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, just like React, it's easy to build an inaccessible component with Svelte. But because Svelte is relatively small, there aren't any battle-tested, widely used component libraries that are more likely to be accessible and there's less for Svelte devs to reuse.&lt;/p&gt;

&lt;p&gt;But Svelte's compiler has accessibility warnings, right? So won't that make my Svelte app accessible?&lt;/p&gt;

&lt;p&gt;Well, it's complicated. But in summary—no.&lt;/p&gt;

&lt;h2&gt;
  
  
  What accessibility issues does the Svelte compiler catch?
&lt;/h2&gt;

&lt;p&gt;First, I want to review which accessibility issues the compiler will warn you about. You can find all the warnings listed in the &lt;a href="https://svelte.dev/docs#Accessibility_warnings"&gt;Svelte docs&lt;/a&gt;. In addition, the code behind these warnings is very readable. If you're interested, look at the &lt;a href="https://github.com/sveltejs/svelte/blob/master/src/compiler/compile/nodes/Element.ts"&gt;Element.ts&lt;/a&gt; file in the Svelte compiler and search for "a11y".&lt;/p&gt;

&lt;p&gt;Reviewing each warning individually could get pretty dry, so I'll provide a high-level overview of the types of issues that will trigger a compiler warning.&lt;/p&gt;

&lt;p&gt;Most of Svelte's accessibility warnings focus around attributes on single HTML elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;required attributes that are missing (e.g. no &lt;code&gt;alt&lt;/code&gt; attribute)&lt;/li&gt;
&lt;li&gt;misplaced attributes that shouldn't be there (e.g. &lt;code&gt;aria-hidden&lt;/code&gt; on a heading)&lt;/li&gt;
&lt;li&gt;invalid attributes (e.g. writing &lt;code&gt;role="potato"&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also some checks around the structure of the markup in a single component, e.g.:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;figcaption&amp;gt;&lt;/code&gt; should be a child of &lt;code&gt;&amp;lt;figure&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;label should have a &lt;code&gt;for&lt;/code&gt; attribute or a child &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;anchors and headings should have child text content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest of the warnings are a grab bag of accessibility best practices—markup that is technically valid, but is not recommended due to its accessibility impact, e.g.:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't use &lt;code&gt;&amp;lt;marquee /&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Don't use &lt;code&gt;autofocus&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Don't use positive &lt;code&gt;tabindex&lt;/code&gt; values&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of Svelte's checks are copied from &lt;a href="https://github.com/jsx-eslint/eslint-plugin-jsx-a11y#supported-rules"&gt;eslint-plugin-jsx-a11y&lt;/a&gt;. There is also &lt;a href="https://github.com/sveltejs/svelte/issues/820"&gt;an open GitHub issue&lt;/a&gt; detailing additional checks the Svelte team would like to add.&lt;/p&gt;

&lt;h2&gt;
  
  
  What issues will the compiler overlook?
&lt;/h2&gt;

&lt;p&gt;However, even if all the suggested rules in the above GitHub issue were added, there are still large categories of issues that the Svelte compiler will overlook. If you take one thing away from this post, let it be this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Just because you don't see any Svelte compiler warnings doesn't mean you made an accessible website.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I will focus on issues that aren't detected because they're difficult or impossible to detect with a compiler, not just because no one has implemented them yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic values
&lt;/h3&gt;

&lt;p&gt;If the value of an attribute is dynamic, the compiler can't be sure what will be placed in that attribute at runtime and will not validate that value.&lt;/p&gt;

&lt;p&gt;For example, the compiler warns you if you write &lt;code&gt;&amp;lt;a href="#"&amp;gt;&lt;/code&gt;. But if you make a variable that stores &lt;code&gt;"#"&lt;/code&gt; and set href to that variable, the compiler won't warn you. This also applies if the value of that attribute is a component prop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;{href}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;I'm under the radar&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't a warning because it's hard for the compiler to determine all the possible values for that variable at compilation time, especially if that variable is populated by an external API response. It can't know if the value of that attribute is an accessibility issue or not.&lt;/p&gt;

&lt;p&gt;This limitation is true for any attribute that the compiler would normally warn you about.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anything that requires a larger view of the app
&lt;/h3&gt;

&lt;p&gt;Not everything can be detected at the component level. Some issues depend on how the component is used in an application, or on an element present in another component. Many of these checks are easier to do at runtime with a tool like &lt;a href="https://www.deque.com/axe/devtools/"&gt;Axe&lt;/a&gt;, which has a full view of the rendered application. Svelte's compiler only looks at one component at a time, and has a limited view of the app as a whole.&lt;/p&gt;

&lt;p&gt;For example, you shouldn't &lt;a href="https://www.w3.org/WAI/tutorials/page-structure/headings/"&gt;skip heading levels&lt;/a&gt; and go from an &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; to an &lt;code&gt;&amp;lt;h4&amp;gt;&lt;/code&gt;. However, if each heading is in a different component, Svelte won't know that you're skipping a heading level. It's not possible to determine that using static analysis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Heading2.svelte --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Heading4.svelte --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h4&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/h4&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- App.svelte --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Heading2&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Heading2.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Heading4&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Heading4.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;Heading2&amp;gt;&lt;/span&gt;
    I'm an h2
&lt;span class="nt"&gt;&amp;lt;/Heading2&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;Heading4&amp;gt;&lt;/span&gt;
    I'm an h4
&lt;span class="nt"&gt;&amp;lt;/Heading4&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, &lt;a href="https://dequeuniversity.com/rules/axe/3.5/duplicate-id"&gt;duplicate IDs&lt;/a&gt; can be an accessibility issue. If two inputs have the same ID, the browser won't know which label goes with which input. However, if you use the same ID in two different Svelte components, the compiler won't be able to determine if that's an issue. Even if it was looking for duplicate IDs, it doesn't know if those two components are ever rendered at the same time.&lt;/p&gt;

&lt;p&gt;Even warnings the Svelte compiler does have, like &lt;a href="https://svelte.dev/docs#a11y-label-has-associated-control"&gt;labels must be linked to an input&lt;/a&gt;, aren't perfect and have blind spots. With the way this warning is currently implemented, Svelte only requires the label to have a &lt;code&gt;for&lt;/code&gt; attribute or to wrap an input. It doesn't require an input with the matching &lt;code&gt;id&lt;/code&gt; to exist or for the input to be associated with a label.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- This passes, even if there is no input with id="test" --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/label&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- This passes, even though there is no associated label --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is because it's very hard for the compiler to be certain that there is an accessibility issue here. In the first case, there could be an input with &lt;code&gt;id="test"&lt;/code&gt; &lt;em&gt;somewhere&lt;/em&gt;, be that another component or even outside the Svelte app entirely. The second case with the standalone input could be easier to detect, but any implementation would likely introduce false positives, where the compiler reports an accessibility issue that is not there.&lt;/p&gt;

&lt;p&gt;This is one of the central conundrums of the Svelte compiler's accessibility checks: finding the balance between false positives and false negatives. The compiler optimizes for &lt;em&gt;false negatives&lt;/em&gt;, or not reporting accessibility issues that are present, so that the number of &lt;em&gt;false positives&lt;/em&gt; is minimized. If there are too many false positives, people stop trusting the accessibility warnings. However, this means there are many potential accessibility issues that the compiler will not detect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Styling issues
&lt;/h3&gt;

&lt;p&gt;If the accessibility issue is in CSS, Svelte won't detect it. Two examples of these issues are making sure your text has appropriate &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast"&gt;color contrast&lt;/a&gt; and that &lt;a href="https://www.deque.com/blog/accessible-focus-indicators/"&gt;keyboard focus&lt;/a&gt; is visible when navigating the page.&lt;/p&gt;

&lt;p&gt;These issues are unlikely to become a compiler warning. As above, this is way easier to check in the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anything that's subjective
&lt;/h3&gt;

&lt;p&gt;If it can't be a straightforward yes/no answer, the compiler is not going to warn you about it. Svelte's current accessibility checks are just lint rules: they're going to help you get the little things right, but they're not going to guarantee that you've written good code. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is animation on the page going to &lt;a href="https://web.dev/prefers-reduced-motion/"&gt;trigger motion sickness&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Is there a better &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML"&gt;semantic HTML&lt;/a&gt; element you could use?&lt;/li&gt;
&lt;li&gt;Is your &lt;a href="https://webaim.org/techniques/alttext/"&gt;alt text&lt;/a&gt; meaningful? Is that image really decorative?&lt;/li&gt;
&lt;li&gt;Is the page usable when used with &lt;a href="https://webaim.org/articles/visual/lowvision#magnifiers"&gt;screen magnification&lt;/a&gt; software?&lt;/li&gt;
&lt;li&gt;Is your custom dropdown/modal/autocomplete usable by a screen reader? By voice controls? By someone only using the keyboard?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Accessibility can't be reduced to a series of compiler warnings. So much about accessibility is a spectrum, not a binary yes/no. These just aren't things that a automated checker can be certain about.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summing up
&lt;/h3&gt;

&lt;p&gt;Those are some of the issues the compiler is unlikely to warn you about anytime soon. And I don't think we should expect it to. There are limitations to being a compiler, and many of these issues are much easier to check in the browser using another automated tool or though manual testing.&lt;/p&gt;

&lt;p&gt;And honestly, there are limits to automated accessibility checks. In general, passing some sort of automated accessibility check is &lt;strong&gt;not&lt;/strong&gt; a guarantee that your page is accessible, the Svelte compiler included. For more on this, I recommend &lt;a href="https://accessibility.blog.gov.uk/2017/02/24/what-we-found-when-we-tested-tools-on-the-worlds-least-accessible-webpage/"&gt;"What we found when we tested tools on the world’s least-accessible webpage"&lt;/a&gt; and &lt;a href="https://www.matuzo.at/blog/building-the-most-inaccessible-site-possible-with-a-perfect-lighthouse-score/"&gt;"Building the most inaccessible site possible with a perfect Lighthouse score."&lt;/a&gt; As developers, we can't pass the responsibility of making our sites accessible to an automated tool.&lt;/p&gt;

&lt;p&gt;The question is: do Svelte developers understand these limitations exist?&lt;/p&gt;

&lt;h2&gt;
  
  
  False confidence
&lt;/h2&gt;

&lt;p&gt;I put a &lt;a href="https://twitter.com/geoffrich_/status/1381999698643275777"&gt;poll on Twitter&lt;/a&gt; a few months ago:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I expect Svelte's accessibility warnings to catch ____ a11y issues.&lt;/p&gt;

&lt;p&gt;Where a11y issue is anything that impacts the accessibility of a page (misused attributes, keyboard focus, color contrast, etc)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some (&amp;lt;20% of issues)&lt;/li&gt;
&lt;li&gt;Many (20-50%)&lt;/li&gt;
&lt;li&gt;Most (&amp;gt;50%)&lt;/li&gt;
&lt;li&gt;All a11y issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;— &lt;a href="https://twitter.com/geoffrich_/status/1381999698643275777"&gt;@geoffrich_&lt;/a&gt; on April 13, 2021&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can't really quantify a11y compliance with percentages—calling your app "80% accessible" is nonsensical. But I wanted to understand people's confidence. If you're building your app in Svelte and you know Svelte has accessibility warnings, what do you think seeing no accessibility warnings means? Does it mean your app is fully accessible? And the results were surprising:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Most a11y issues (28.5% of respondents)&lt;/li&gt;
&lt;li&gt;Some a11y issues (26.3%)&lt;/li&gt;
&lt;li&gt;All a11y issues (24%)&lt;/li&gt;
&lt;li&gt;Many a11y issues (21.2%)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Out of 300 respondents, over half (52%) thought Svelte would catch most or all a11y issues. Almost a quarter thought Svelte would catch all of them. And I don't think that's a correct perception. With my examples above, it's clear that there's so much more to accessibility that Svelte won't warn you about.&lt;/p&gt;

&lt;p&gt;Even beyond Svelte, automated accessibility checkers don't catch every issue. According to WebAIM, only &lt;a href="https://webaim.org/projects/million/#method"&gt;25%-35% of accessibility errors&lt;/a&gt; are detectable using any automated tooling, and the Svelte compiler is a subset of that. You're mistaken if you think using Svelte will mean you're warned about any accessibility issue.&lt;/p&gt;

&lt;p&gt;I want to emphasize that &lt;em&gt;Svelte hasn't promised that&lt;/em&gt;—there's no false advertising happening here. But there also isn't a lot of documentation on Svelte's accessibility warnings. Accessibility is mentioned in the &lt;a href="https://svelte.dev/tutorial/dynamic-attributes"&gt;tutorial&lt;/a&gt; once. If you're unfamiliar with accessibility, I see how you could assume that it's something the compiler takes care of, just like the compiler takes care of optimizing your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  How could Svelte be better?
&lt;/h2&gt;

&lt;p&gt;Developers will always have to do something to make sure what they build is accessible. However, I have a few suggestions for Svelte to improve its accessibility tooling and documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrate with existing tooling
&lt;/h3&gt;

&lt;p&gt;A lot of the existing a11y warnings have been slow to implement because Svelte has to re-implement work already done in the &lt;a href="https://github.com/jsx-eslint/eslint-plugin-jsx-a11y"&gt;JSX eslint&lt;/a&gt; plugin or in &lt;a href="https://github.com/dequelabs/axe-core"&gt;axe-core&lt;/a&gt;. Is there a way to use existing packages in the Svelte compiler to detect a11y issues? Building a compiler is hard enough, let alone keeping up to date with accessibility guidance.&lt;/p&gt;

&lt;p&gt;Also, with &lt;a href="https://kit.svelte.dev/"&gt;SvelteKit&lt;/a&gt;, we now know how someone will be building their Svelte app. There could be a way to integrate runtime accessibility checks into the default template. Adding these checks would massively increase the kinds of issues Svelte could detect. I put in a &lt;a href="https://github.com/sveltejs/kit/issues/1265"&gt;SvelteKit issue&lt;/a&gt; suggesting that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Merge existing PRs
&lt;/h3&gt;

&lt;p&gt;There are quite a few a11y warning PRs open. Merging these PRs would improve Svelte's existing accessibility tooling.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/sveltejs/svelte/pull/5852"&gt;role-has-required-aria-props&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sveltejs/svelte/pull/5955"&gt;noninteractive-roles-on-interactive-elements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sveltejs/svelte/pull/5073"&gt;click-events-have-key-events&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sveltejs/svelte/pull/5361"&gt;no-redundant-roles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sveltejs/svelte/pull/6693"&gt;no-nointeractive-tabindex&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sveltejs/svelte/pull/6652"&gt;click-events-have-key-events&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sveltejs/svelte/pull/6316"&gt;valid-aria-proptypes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Documentation
&lt;/h3&gt;

&lt;p&gt;I also think Svelte could improve its documentation around accessibility. Currently, it only lists the available &lt;a href="https://svelte.dev/docs#a11y-label-has-associated-control"&gt;accessibility warnings&lt;/a&gt;. &lt;a href="https://reactjs.org/docs/accessibility.html"&gt;React,&lt;/a&gt; &lt;a href="https://v3.vuejs.org/guide/a11y-basics.html"&gt;Vue,&lt;/a&gt; and &lt;a href="https://angular.io/guide/accessibility"&gt;Angular&lt;/a&gt; all have dedicated accessibility sections in their docs. These sections detail various considerations, practices, and testing around accessibility. Svelte could do the same, or at least link out to further resources. This would help developers better understand what they're responsible for.&lt;/p&gt;

&lt;h3&gt;
  
  
  Foster a culture of accessibility
&lt;/h3&gt;

&lt;p&gt;This isn't necessarily on Svelte itself, but on the community. As Svelte developers and content creators, we should take care to make sure what we put out there is accessible, whether that's a blog post, a video, sharing a REPL, or creating a package. Sharing inaccessible demos (for example, a demo that uses &lt;code&gt;&amp;lt;div on:click&amp;gt;&lt;/code&gt; instead of &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;) results in people copying that code for their projects and excluding some of their users. We can do better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;As a developer, you should take ownership of the accessibility of what you build. Releasing an inaccessible app or site does harm to your users. The Svelte compiler will help you write accessible markup, but it won't catch everything—you still need to test your sites for accessibility in other ways. You don't have to be an expert, but you do have to care.&lt;/p&gt;

&lt;p&gt;Here's some things you can do that will make a difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run other checkers like &lt;a href="https://www.deque.com/axe/devtools/"&gt;Axe,&lt;/a&gt; &lt;a href="https://wave.webaim.org/"&gt;WAVE,&lt;/a&gt; or &lt;a href="https://web.dev/lighthouse-accessibility/"&gt;Lighthouse&lt;/a&gt; on your webpage.&lt;/li&gt;
&lt;li&gt;Make sure you can navigate your site only using your keyboard.&lt;/li&gt;
&lt;li&gt;Continue learning about accessibility.&lt;/li&gt;
&lt;li&gt;Learn how to use a screen reader.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll link some introductory a11y resources down below, and feel free to reach out to me on Twitter or in the Svelte Discord if you have any questions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We can help educate developers about a11y and make a strong statement about the kind of web we want to be a part of — I think we should.&lt;/p&gt;

&lt;p&gt;— &lt;a href="https://github.com/sveltejs/svelte/issues/374"&gt;Rich Harris&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Further a11y resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility"&gt;MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.a11yproject.com/"&gt;The A11y Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.smashingmagazine.com/2021/03/complete-guide-accessible-front-end-components/"&gt;Smashing Magazine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.accessibility-developer-guide.com/"&gt;Accessibility Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PLNYkxOF6rcICWx0C9LVWWVqvHlYJyqw7g"&gt;A11ycasts with Rob Dodson&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="https://www.swyx.io/"&gt;swyx&lt;/a&gt; for discussing these ideas with me back when this was a rejected Svelte Summit talk.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>javascript</category>
      <category>a11y</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Exploring Marvel Comics' history with SvelteKit</title>
      <dc:creator>Geoff Rich</dc:creator>
      <pubDate>Wed, 06 Oct 2021 15:52:20 +0000</pubDate>
      <link>https://dev.to/geoffrich/exploring-marvel-comics-history-with-sveltekit-16pf</link>
      <guid>https://dev.to/geoffrich/exploring-marvel-comics-history-with-sveltekit-16pf</guid>
      <description>&lt;p&gt;&lt;em&gt;tl;dr I launched a &lt;a href="https://marvel.geoffrich.net/" rel="noopener noreferrer"&gt;new site&lt;/a&gt; where you can see Marvel comics published in a &lt;a href="https://marvel.geoffrich.net/year" rel="noopener noreferrer"&gt;given year&lt;/a&gt; and retrieve a &lt;a href="https://marvel.geoffrich.net/comic/random" rel="noopener noreferrer"&gt;random comic&lt;/a&gt; available on the Marvel Unlimited app. The code is &lt;a href="https://github.com/geoffrich/marvel-by-year" rel="noopener noreferrer"&gt;open source&lt;/a&gt; on GitHub.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On September 9, the Marvel Unlimited app (MU), which lets you read tens of thousands of Marvel's comics for a monthly fee, got a huge update. While it added some long awaited features such as unlimited downloads, it also wreaked havoc on users' reading history and libraries and removed some beloved features.&lt;/p&gt;

&lt;p&gt;One of these features was the ability to sort by date—for example, being able to view every comic released in 1993. This was crucial for those trying to read every Marvel comic in chronological order, as well as those following a yearly comic book reading club like &lt;a href="https://www.comicbookherald.com/my-marvelous-year/" rel="noopener noreferrer"&gt;My Marvelous Year&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I was one of those users disappointed by the feature's removal. After I discovered that all the data needed to re-create the feature was available from &lt;a href="https://developer.marvel.com/" rel="noopener noreferrer"&gt;Marvel's API&lt;/a&gt;, I started coding. A few weeks later I launched &lt;a href="https://marvel.geoffrich.net/" rel="noopener noreferrer"&gt;Marvel Unlimited by Year&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmkgz9a9b4y8ybhsr2qg.png" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot of the 1977 comics page. The first three titles are shown: Champions #10, Thor #255, and Incredible Hulk #207" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmkgz9a9b4y8ybhsr2qg.png"&gt;&lt;/a&gt;&lt;/p&gt;
Comics available on MU published in 1977



&lt;ul&gt;
&lt;li&gt;View all comics available on Marvel Unlimited for a given year. For example, here's &lt;a href="https://marvel.geoffrich.net/year/1975" rel="noopener noreferrer"&gt;1975&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Each comic's cover links directly to the issue in Marvel Unlimited or the web-based reader, depending on your device.&lt;/li&gt;
&lt;li&gt;Sort and filter the results by series, creator, or event.&lt;/li&gt;
&lt;li&gt;View a &lt;a href="https://marvel.geoffrich.net/comic/random" rel="noopener noreferrer"&gt;random selection&lt;/a&gt; of available comics, or random comics released in a specific decade. The old app had a button that would give you a random comic, though it wouldn't allow you to specify the decade. The MU team have stated that they &lt;a href="https://www.reddit.com/r/MarvelUnlimited/comments/py12lt/hi_mu_subreddit_were_the_team_behind_marvel/herewi5/" rel="noopener noreferrer"&gt;don't have plans&lt;/a&gt; to add the random button to the new app, so I'm glad I was able to make it available on my site.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymwlqhkd3zxu92rdnpxk.png" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot of the random comics page. 6 covers are shown: Dr. Strange Sorcerer Supreme, Star Wars Dark Empire II1, Marvel Digital Holiday Special, History of the Marvel Universe, New X-Men, and Luke Cage: Power Man." src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymwlqhkd3zxu92rdnpxk.png"&gt;&lt;/a&gt;&lt;/p&gt;
The random comics page




&lt;h2&gt;
  
  
  The tech stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://svelte.dev/" rel="noopener noreferrer"&gt;Svelte&lt;/a&gt; and &lt;a href="https://kit.svelte.dev/" rel="noopener noreferrer"&gt;SvelteKit&lt;/a&gt; for the app framework. This was my first major project in SvelteKit and I had a great experience. Svelte is my favorite front-end framework to work in, and SvelteKit builds a full-stack app framework on top of it with SSR, server endpoints, and routing, as well as a fast dev environment powered by &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt;. Despite it still being pre-1.0, I had very few issues and I'm looking forward to moving some of my work projects over to SvelteKit as soon as possible.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt; on the server and client side. The complexity of the API response made auto-complete a must-have (and by extension, types). SvelteKit gave me the option to set this up automatically, so I didn't have to wrangle any configuration.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://redis.io/" rel="noopener noreferrer"&gt;Redis&lt;/a&gt; cache hosted on &lt;a href="https://upstash.com/" rel="noopener noreferrer"&gt;Upstash&lt;/a&gt;, a serverless option where you pay per-request instead of per-server. Since I had a limited number of API requests per-day, I needed to cache the responses for 24 hours. The &lt;a href="https://marvel.geoffrich.net/comic/random" rel="noopener noreferrer"&gt;random comic&lt;/a&gt; functionality is also implemented using Redis queries.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; hosted the deployed site. So far, the traffic hasn't exceeded the limits of their free plan (125k function invocations).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.marvel.com/" rel="noopener noreferrer"&gt;Marvel API&lt;/a&gt; for the data. While the documentation doesn't seem like it's been updated recently (the last change announcement was 2014), it still works great and the data is current.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testimonials
&lt;/h2&gt;

&lt;p&gt;I posted this project on the &lt;a href="https://www.reddit.com/r/MarvelUnlimited/comments/pxe7l9/i_made_a_site_that_lets_you_browse_mu_by_release/" rel="noopener noreferrer"&gt;Marvel Unlimited subreddit&lt;/a&gt; last week, and received a glowing response.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Uh, I think I can speak for everyone when I say, holy cow this is great! Super fast and the link to the iOS app works great! I guess it’s true what they say, not all heroes wear capes. I wish I could upvote this multiple times!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;Even better than the old app because it does exactly what I used to do, but it loads so much faster!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;This is the best thing I've ever seen on Reddit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It was nice to develop something that others found useful! One of the best things about knowing how to code is being able to create something solving a niche problem that wouldn't otherwise get addressed. These comments also show that &lt;strong&gt;SvelteKit provides a speedy user experience as well as a great dev experience.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As a dev myself, I know as well as anyone that rewriting a product with an existing user base is hard. I'm not trying to disparage the development team as part of this effort—I just wanted to restore a feature that I (and many others) found essential, and try out some new dev tools in the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future plans
&lt;/h2&gt;

&lt;p&gt;I'm not done developing this site and still have some features I want to add, such as filtering by release month and listing out available series.&lt;/p&gt;

&lt;p&gt;If you're interested, the code is &lt;a href="https://github.com/geoffrich/marvel-by-year" rel="noopener noreferrer"&gt;open source&lt;/a&gt; on GitHub. You can even run it yourself, though you'll need to provide your own Marvel API keys and Redis connection. Docs are sparse at the moment, though I hope to flesh them out eventually.&lt;/p&gt;

&lt;p&gt;Stay tuned for a follow-up post with some of the things I learned on this project.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@introspectivedsgn?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Erik Mclean&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>javascript</category>
      <category>showdev</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>Notes on Rich Harris' PodRocket interview</title>
      <dc:creator>Geoff Rich</dc:creator>
      <pubDate>Tue, 05 Oct 2021 18:21:22 +0000</pubDate>
      <link>https://dev.to/geoffrich/notes-on-rich-harris-podrocket-interview-2anm</link>
      <guid>https://dev.to/geoffrich/notes-on-rich-harris-podrocket-interview-2anm</guid>
      <description>&lt;p&gt;LogRocket's podcast &lt;a href="https://podrocket.logrocket.com/"&gt;PodRocket&lt;/a&gt; released a &lt;a href="https://podrocket.logrocket.com/rich-harris"&gt;new episode&lt;/a&gt; with Rich Harris, the creator of &lt;a href="https://svelte.dev/"&gt;Svelte&lt;/a&gt;, this morning. There were so many good insights in it that I wanted to pull out some choice quotes and take some notes to share this in a non-audio medium.&lt;/p&gt;

&lt;p&gt;I highly recommend listening to the full episode, especially if you're new to Svelte. Even if you're already familiar with Svelte, there are still some great insights to Svelte's philosophy and its position in the current framework landscape.&lt;/p&gt;

&lt;p&gt;All these quotes are from Rich Harris. I pulled them from the &lt;a href="https://assets.fireside.fm/file/fireside-images/podcasts/transcripts/3/3911462c-bca2-48c2-9103-610ba304c673/episodes/8/8a485d85-aea7-4811-86c6-de00f8399413/transcript.txt"&gt;transcript&lt;/a&gt; of the episode and cleaned them up a bit, though the emphasis is mine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Svelte's advantages
&lt;/h2&gt;

&lt;p&gt;Svelte's advantage is that it lets you write your components declaratively, and then translates it into the underlying DOM manipulation at compile time. This typically makes for smaller bundle size and faster state updates.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Instead of imperatively manipulating the DOM with &lt;code&gt;document.createElement&lt;/code&gt; and all of the things that are provided by the platform. It puts a declarative layer on top of that so that you can describe the output that you want, and then the framework's job is to translate that into the underlying DOM manipulations.&lt;/p&gt;

&lt;p&gt;It generates typically very small code, which means that your application is going to load very quickly, and the updates, when you have a state change within your application, also take place very quickly, because it doesn't need to regenerate your entire application. It's just surgically updating the part of the page that's affected.&lt;/p&gt;

&lt;p&gt;I should say at this point, because this is what I've been telling people about Svelte since it first came around in 2016, the landscape has actually shifted a little bit and other frameworks are, in many cases, becoming a little bit more Svelte-like. So when I talk about these unique advantages, they're not so unique anymore. &lt;strong&gt;Svelte's selling point these days is really more about the developer experience it provides.&lt;/strong&gt; Vue, in particular, has adopted a lot of these techniques and also has some of those bundle size and performance characteristics.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Just JavaScript vs a DSL
&lt;/h2&gt;

&lt;p&gt;There are advantages to staying close to the platform and only using syntax that exists natively, but domain-specific languages (DSLs) have advantages too.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One of the things I say from time to time is that DSLs are actually a good thing. People on the other side, on the just JavaScript side, will be like, "I don't want to learn a domain specific language," because they've been bitten by domain specific languages in the past. But, actually, &lt;strong&gt;why wouldn't you want the language to be specific to the domain that you're solving.&lt;/strong&gt; As long as the DSL doesn't decrease the amount of flexibility that you have, then other things being equal, it's probably a good thing. If it enables you to express the ideas in your application more concisely and more consistently, then it's probably a good thing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Svelte's primary language is HTML
&lt;/h2&gt;

&lt;p&gt;Svelte's component syntax uses HTML as a base—the fundamental language of the web.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The thesis here is the HTML is the language of the web. JavaScript is not the language of the web. JavaScript is one of the three languages that are sort of contained within HTML, because HTML is designed to contain CSS and JavaScript, whereas a lot of frameworks go the other way. They're like, "JavaScript is the primary language and we're going to try and shoehorn HTML and, in some cases, CSS into JavaScript." &lt;strong&gt;Svelte takes this opposite view that you begin with HTML, and then you add JavaScript as necessary.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  On SvelteKit's flexibility
&lt;/h2&gt;

&lt;p&gt;SvelteKit is a framework built for the serverless front-end landscape.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's a full stack application framework that lets you build fully server rendered applications with all of the modern best practices, but it's also very flexible both in how you build your app. You can build a completely single-page app or you can build a completely JavaScript-free multi-page app or something in between, and you can vary it by page; but you can also deploy it to a bunch of different places if it's suitable. Like [if] you're building a very static content site, then you can bake it out of static HTML and then you can just throw that on GitHub Pages or whatever it is.&lt;/p&gt;

&lt;p&gt;But if you're doing something that's highly dynamic, then you can have a server component or you can have serverless functions or you can put it inside a Cloudflare Worker, and you can pre-render the parts of your application that are static and dynamically render the parts that are not. And it's really a way of addressing all of the problems, or as many of the problems as possible, that you encounter while building a modern web application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For more on this topic, see the &lt;a href="https://svelte.dev/blog/whats-the-deal-with-sveltekit"&gt;SvelteKit announcement post&lt;/a&gt;, though some things have changed since that was written. Most notably, SvelteKit is now using &lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt; instead of Snowpack.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's on the Svelte roadmap?
&lt;/h2&gt;

&lt;p&gt;I liked hearing about what could be next for Svelte, though note that nothing on this list is set in stone. It seems like we can expect more iteration on Svelte core once SvelteKit hits 1.0 and is stable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm almost reluctant to talk about some of these things, because &lt;strong&gt;a lot of it is speculative and we're not really sure where some of these ideas are going to land.&lt;/strong&gt; But we have this long wish list of things that we want to do for Svelte 4.0 and beyond.&lt;/p&gt;

&lt;p&gt;Some of it is adopting some of the features that other frameworks have proven out, like &lt;strong&gt;streaming SSR&lt;/strong&gt; and things like that. Some of it is around &lt;strong&gt;speeding up our own compiler&lt;/strong&gt;, so that the feedback loop gets even tighter. Changing how the compiled output is generated such that if you have a very large application, you're &lt;strong&gt;paying only a very tiny incremental cost per component&lt;/strong&gt;. We have some grand ideas about better ways to think about &lt;strong&gt;motion inside user interfaces&lt;/strong&gt; and how that should be tied to the core of a framework as opposed to left to a userland solution.&lt;/p&gt;

&lt;p&gt;We have a great many ideas, and I don't want to give them all away. But there's a lot on our plate, and we're pretty excited to get stuck into it when we can.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Does Svelte have more "magic" than something like React?
&lt;/h2&gt;

&lt;p&gt;A common perception is that Svelte has more magic as opposed to a framework like React. However, React has magic too—the difference is that Svelte's magic happens at compile time, while React's magic happens at runtime.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I don't know that that [magic vs explicit is] such a real dichotomy. The differences that Svelte is doing the stuff at build time. It's changing your expectations of how JavaScript works, because it's intercepting assignments and turning those into reactive state changes. React is doing something similar.&lt;/p&gt;

&lt;p&gt;If you look at a React function and you don't know what's happening with hooks, then you would look at that code and you'd be very confused about what's happening, because the functions behave in ways that JavaScript functions generally don't. The fact that the return value of a function depends on how many times you've called that function and whether you've called the return value in the past and things like that, that's deeply weird, it's not how JavaScript works at all. You can implement it with JavaScript, but it's not how JavaScript works. They are violating expectations on a fairly fundamental level.&lt;/p&gt;

&lt;p&gt;The difference is that they're doing it all at runtime instead of having all of that stuff happen behind the scenes at compile time. And I tend to think that focusing on whether the magic happens at build time or whether it happens at runtime is focusing on the wrong thing. &lt;strong&gt;All frameworks involve magic. Svelte is just trying to do the expensive bits of magic before that code gets to the user. That's the only real difference.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  On the "framework wars"
&lt;/h2&gt;

&lt;p&gt;Treating web development as a war between one framework or another is not healthy. The people building these frameworks get along and are all trying to improve front-end development and the web as a whole. There is no One True Framework, and different frameworks fill different needs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I dislike the framework wars framing generally, because what might not be obvious to a lot of people who are users of these frameworks as opposed to actively involved in the development of them, is that... The people who are building these frameworks, we often talk to each other. We by and large know each other. We get along. There's no animosity There's no warring whatsoever.&lt;/p&gt;

&lt;p&gt;We hang out in the same spaces and we share ideas with each other, and really we're all, I think, just trying to collectively advance the state of front end development by focusing on the little bits of innovation that we can contribute, and then gradually, all of that stuff filters through the ecosystem and gets shared more widely. And Svelte occupies a part of the landscape that is attractive to a certain kind of developer. React occupies a different part of the landscape. &lt;strong&gt;They're both completely fine solutions for the people who are choosing them, and they're not going to be right for everyone and that's fine.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Svelte is no longer an underdog
&lt;/h2&gt;

&lt;p&gt;Svelte is now talked about as one of the "big 4" frameworks. At this point, we can't really consider it an underdog, since so many are aware of it. There are many frameworks with much less name recognition than Svelte.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So are we the underdog? It depends on what you're looking at. There's three big frameworks, right? There's React, Angular and Vue. And if you had to pick a fourth framework, I think most people at this stage would probably say the fourth framework was Svelte. And so if underdog means that you're inside the top four instead of the top three, then absolutely are the underdog.&lt;/p&gt;

&lt;p&gt;At the same time, we have a pretty good mindshare at this point. A lot of people in the front end world have heard of Svelte. A lot of people talk about Svelte. There's a whole industry of people doing YouTube videos about Svelte. &lt;strong&gt;And I think calling ourselves underdog would be a disservice to the people who are actually laboring on open source projects without getting a whole lot of recognition.&lt;/strong&gt; I think we have plenty of recognition. And so, I wouldn't claim the underdog label for ourselves by any stretch, but nor are we in any way mainstream.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  See the podcast for more, including
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How Svelte compares to the virtual DOM (see also: &lt;a href="https://svelte.dev/blog/virtual-dom-is-pure-overhead"&gt;Virtual DOM is pure overhead&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The ideal use case for Svelte&lt;/li&gt;
&lt;li&gt;Svelte's two-pronged approach to managing state&lt;/li&gt;
&lt;li&gt;How templating works in svelte&lt;/li&gt;
&lt;li&gt;Whether a React-specific DSL could help reduce its boilerplate (see also Rich's &lt;a href="https://twitter.com/Rich_Harris/status/1438502561942810625?s=20"&gt;tweet&lt;/a&gt; on the subject)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>svelte</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How Svelte scopes component styles</title>
      <dc:creator>Geoff Rich</dc:creator>
      <pubDate>Tue, 07 Sep 2021 13:57:57 +0000</pubDate>
      <link>https://dev.to/geoffrich/how-svelte-scopes-component-styles-32e3</link>
      <guid>https://dev.to/geoffrich/how-svelte-scopes-component-styles-32e3</guid>
      <description>&lt;p&gt;By default, any styles you write in a Svelte component are scoped to that component. This means that the &lt;code&gt;p&lt;/code&gt; selector in the following code will only apply to &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; elements inside this component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is a paragraph with scoped styles.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;/* I only affect elements in this component */&lt;/span&gt;
  &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But how does this scoping actually work? In this post, I'll explain how Svelte scopes styles to your components and the implications for global styles in the rest of your app. I think this topic is interesting on its own, but understanding Svelte's scoping method will also help you better debug your component styles.&lt;/p&gt;

&lt;p&gt;This post is accurate for the Svelte version at time of writing (v3.42.4). However, the implementation of Svelte's style scoping is subject to change—in Svelte's lifespan, it has changed &lt;a href="https://github.com/sveltejs/svelte/pull/607"&gt;several&lt;/a&gt; &lt;a href="https://github.com/sveltejs/svelte/pull/1192"&gt;times&lt;/a&gt; &lt;a href="https://github.com/sveltejs/svelte/pull/4146"&gt;already&lt;/a&gt;—and I don't guarantee that this post will remain accurate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Classing up the joint
&lt;/h2&gt;

&lt;p&gt;When working on a Svelte app, you may have seen some unexpected CSS classes beginning with "svelte-" in the DevTools inspector. Why are those there? Svelte applies those classes to styled elements in your app so that component styles don't "leak out" to elements outside the component.&lt;/p&gt;

&lt;p&gt;For example, the component in the previous section is transformed into the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"svelte-dvinuz"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;This is a paragraph with scoped styles.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="nc"&gt;.svelte-dvinuz&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The transformed CSS rule won't apply to &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; elements outside of the component, because they won't have the &lt;code&gt;svelte-dvinuz&lt;/code&gt; CSS class applied. Only elements inside the component will match the scoped CSS rule.&lt;/p&gt;

&lt;p&gt;The class Svelte adds is not random. It is generated using a hash of the component's styles, making it unique for every component (unless two components styles are &lt;strong&gt;exactly&lt;/strong&gt; the same).&lt;/p&gt;

&lt;h2&gt;
  
  
  More complex rules
&lt;/h2&gt;

&lt;p&gt;Let's look at what happens when the CSS rules become more complicated. The following component uses a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_combinator"&gt;descendant combinator&lt;/a&gt;. This is not strictly necessary in this example case (you could target &lt;code&gt;span&lt;/code&gt; and &lt;code&gt;li&lt;/code&gt; directly), but it's useful for illustration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Apples &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;🍎&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Bananas &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;🍌&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Carrots &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;🥕&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;24px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What are the different ways Svelte could transform this component?&lt;/p&gt;

&lt;p&gt;One option is to only apply the scoping class to the first selector in the rule, so the rules become &lt;code&gt;ul.svelte li&lt;/code&gt; and &lt;code&gt;ul.svelte li span&lt;/code&gt;. However, this could cause unwanted style leakage. If this component contained child components, elements in those components could match the rule.&lt;/p&gt;

&lt;p&gt;Another option is to apply the scoping class to every selector in the rule, so the rules would become &lt;code&gt;ul.svelte li.svelte&lt;/code&gt; and &lt;code&gt;ul.svelte li.svelte span.svelte&lt;/code&gt;. This &lt;em&gt;would&lt;/em&gt; prevent any styles from leaking to child components, but it does add the scoping class more times than is necessary. It would also unnecessarily increase specificity, which is a problem we'll return to later.&lt;/p&gt;

&lt;p&gt;What Svelte actually does is somewhere in the middle: it applies the scoping class to the first and last selector of each rule. The styles are transformed to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="nc"&gt;.svelte-gxa857&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nc"&gt;.svelte-gxa857&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="nc"&gt;.svelte-gxa857&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.svelte-gxa857&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;24px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the best of both worlds: styles don't leak out (because the rule must start and end inside the component) and we don't add more classes than necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specificity and scoping
&lt;/h2&gt;

&lt;p&gt;Now if you think you have a handle on things, let's tweak our markup and styles a bit. What styles do you think Svelte generates in this case?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Apples&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;🍎&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Bananas&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;🍌&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Carrots&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;🥕&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;24px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, Svelte outputs the following CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="nc"&gt;.svelte-1pr62yn&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nc"&gt;.svelte-1pr62yn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;24px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.name.svelte-1pr62yn.svelte-1pr62yn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Woah! Svelte transformed the 3-selector rule the same way, but added the hash class &lt;em&gt;twice&lt;/em&gt; to the &lt;code&gt;.name&lt;/code&gt; rule! Why would it do that?&lt;/p&gt;

&lt;p&gt;This traces back to a concept called &lt;em&gt;CSS specificity&lt;/em&gt;. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity"&gt;Specificity&lt;/a&gt; is how the browser determines what CSS rules should take precedence over others. In general, certain types of CSS selectors are more specific and thus have higher priority. For instance, a class selector (like &lt;code&gt;.list&lt;/code&gt;) is more specific than an element selector (like &lt;code&gt;ul&lt;/code&gt;). If both &lt;code&gt;.list&lt;/code&gt; and &lt;code&gt;ul&lt;/code&gt; define a value for font-size, the &lt;code&gt;.list&lt;/code&gt; value will win since it's more specific.&lt;/p&gt;

&lt;p&gt;Also, the amount of each type of selector matters. The more of a type of a selector in a given CSS rule, the more specific it is. So, a selector with two classes will be more specific than a selector with one class.&lt;/p&gt;

&lt;p&gt;I'm drastically over-simplifying things (specificity can support an entire blog post in itself!), so check out &lt;a href="https://web.dev/learn/css/specificity/"&gt;web.dev's Learn CSS module&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;So, the reason Svelte adds two class selectors instead of one is to keep the specificity order intact. Before the scoping classes were added, the rules had the following specificity order (from highest to lowest):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;.name&lt;/code&gt; (specificity 0-1-0)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ul li span&lt;/code&gt; (specificity 0-0-3)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But after the classes were added the specificity changed. Here's what the specificity would've been if Svelte &lt;strong&gt;didn't&lt;/strong&gt; add the hash class twice:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;ul.svelte li span.svelte&lt;/code&gt; (specificity 0-2-3)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.name.svelte&lt;/code&gt; (specificity 0-2-0)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(For how those specificity values were calculated, see the resources linked above or the &lt;a href="https://specificity.keegan.st/"&gt;CSS Specificity Calculator&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Because multi-selector rules have two classes added in the generated styles and single-selector rules only have one, the specificity order of the rules changed. This could mean that different styles take precedence than if Svelte &lt;em&gt;didn't&lt;/em&gt; scope the styles. In our example, the name's font size would be 24px (as defined by &lt;code&gt;ul li span&lt;/code&gt;) instead of 18px (as defined by &lt;code&gt;.name&lt;/code&gt;)—the opposite of what you'd expect looking at the raw CSS.&lt;/p&gt;

&lt;p&gt;Svelte prevents the specificity order from changing in an interesting way. It keeps track of how many classes are added to each CSS rule, and makes sure each rule has its specificity increased by the same amount. Since &lt;code&gt;.name&lt;/code&gt; only had one scoping class applied, Svelte adds a second class to preserve the specificity order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;.name.svelte.svelte&lt;/code&gt; (specificity 0-3-0)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ul.svelte li span.svelte&lt;/code&gt; (specificity 0-2-3)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By making sure the specificity order remains the same, the scoped CSS produces the same result as the raw CSS.&lt;/p&gt;

&lt;p&gt;If you're interested in seeing how this is implemented in the Svelte compiler, see &lt;a href="https://github.com/sveltejs/svelte/pull/4146"&gt;Svelte PR #4146&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specificity wars
&lt;/h2&gt;

&lt;p&gt;Because Svelte's scoping method increases the specificity of your CSS by adding classes, you may run into issues if you have global styles that you expect to be inherited. For instance, let's say you have the following &lt;strong&gt;global&lt;/strong&gt; styles (e.g., in an external stylesheet):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;purple&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in a Svelte component, you override the default link color:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://svelte.dev"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Ordinary link&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"special-link"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://svelte.dev"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Exciting link&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.special-link&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What color would you expect the link to be &lt;em&gt;on hover&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;If you were writing these styles without Svelte's scoping, the link would be red by default (as specified in the component) but green on hover (as specified in the global styles). This is because &lt;code&gt;a:hover&lt;/code&gt; is more specific (0-1-1) than &lt;code&gt;.special-link&lt;/code&gt; (0-1-0). However, because Svelte added a scoping class, we should really be comparing &lt;code&gt;a:hover&lt;/code&gt; to &lt;code&gt;.special-link.svelte&lt;/code&gt;, which has a specificity of 0-2-0. Because of this, the &lt;code&gt;.special-link&lt;/code&gt; styles also apply when the link is hovered, which may be unexpected.&lt;/p&gt;

&lt;p&gt;This problem is exacerbated when Svelte adds multiple scoping classes. If Svelte adds two classes to &lt;code&gt;.special-link&lt;/code&gt;, the component styles will be more specific and even more likely to unintentionally override global styles. Unfortunately, there isn't an easy way to work around this behavior. If you want your global styles to apply in this situation, you'll need to find a way to increase their specificity (e.g. by adding &lt;code&gt;!important&lt;/code&gt; or &lt;a href="https://web.dev/learn/css/specificity/#pragmatically-increasing-specificity"&gt;doubling up on classes&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;There's currently an open &lt;a href="https://github.com/sveltejs/svelte/issues/4374"&gt;Svelte issue&lt;/a&gt; objecting to Svelte adding more than one scoping class, though it's not clear how to solve it without re-introducing the original &lt;a href="https://github.com/sveltejs/svelte/issues/1277"&gt;issue around specificity order&lt;/a&gt;. There isn't an obvious improvement to be made in the Svelte compiler either—Svelte needs to add &lt;em&gt;something&lt;/em&gt; to the CSS rules to make sure they only apply to a single component, and that will increase the specificity. Perhaps &lt;a href="https://drafts.csswg.org/css-scoping-2/#scoped-styles"&gt;native CSS scoping&lt;/a&gt; will help, though the spec is still being drafted. Until then, the cost of Svelte's style scoping is some occasional specificity clashes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;I hope this article helped you understand Svelte's CSS scoping behavior better. Understanding why the compiler makes the decisions it does can help you write better Svelte components and make debugging easier.&lt;/p&gt;

&lt;p&gt;If you're interested in going deeper, consider reading the &lt;a href="https://github.com/sveltejs/svelte/blob/4f9a260ab17a9d2a013a72a4bca3bf96947062c0/src/compiler/compile/css/Stylesheet.ts"&gt;Stylesheet implementation&lt;/a&gt; in the Svelte source code—it's surprisingly readable.&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>css</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
