<?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: Zell Liew 🤗</title>
    <description>The latest articles on DEV Community by Zell Liew 🤗 (@zellwk).</description>
    <link>https://dev.to/zellwk</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%2F64562%2F26c2b9b5-f469-4686-b8f8-53712468e684.jpg</url>
      <title>DEV Community: Zell Liew 🤗</title>
      <link>https://dev.to/zellwk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zellwk"/>
    <language>en</language>
    <item>
      <title>Making a nice neon button</title>
      <dc:creator>Zell Liew 🤗</dc:creator>
      <pubDate>Tue, 17 Oct 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zellwk/making-a-nice-neon-button-ca5</link>
      <guid>https://dev.to/zellwk/making-a-nice-neon-button-ca5</guid>
      <description>&lt;p&gt;When I was building the &lt;a href="https://magicaldevschool.com"&gt;Magical Dev School&lt;/a&gt; website, I accidentally stumbled on a way to make Neon buttons look good.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/uiI7eEUFbc4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;There are three important elements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A little bit of glow around the text&lt;/li&gt;
&lt;li&gt;A larger glow around the button&lt;/li&gt;
&lt;li&gt;A nice zoom effect&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Making the text glow
&lt;/h2&gt;

&lt;p&gt;The trick here is to use &lt;code&gt;drop-shadow&lt;/code&gt; instead of &lt;code&gt;text-shadow&lt;/code&gt; to create the glow effect.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;drop-shadow&lt;/code&gt; works better because it creates a softer and more enveloping blur - very much like how a soft light source would fall into its surroundings.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;text-shadow&lt;/code&gt; is too harsh.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JQmyiNdG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/neon-button/text-vs-drop-shadow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JQmyiNdG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/neon-button/text-vs-drop-shadow.png" width="399" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We only want to use &lt;code&gt;drop-shadow&lt;/code&gt; on the text, so we need to change the markup a little bit to include an extra span element.&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;button&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;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Text goes here &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&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;And we can include the &lt;code&gt;drop-shadow&lt;/code&gt; like this:&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="nc"&gt;.text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;drop-shadow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="n"&gt;currentcolor&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;h2&gt;
  
  
  Making the larger glow around the button
&lt;/h2&gt;

&lt;p&gt;We can make a larger glow around the button with &lt;code&gt;drop-shadow&lt;/code&gt; and &lt;code&gt;box-shadow&lt;/code&gt;. In this case, I prefer &lt;code&gt;box-shadow&lt;/code&gt; over &lt;code&gt;drop-shadow&lt;/code&gt; because I can control the spread.&lt;/p&gt;

&lt;p&gt;This lets me cast a harsher shadow that accentuates the border.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HbWDuTEN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/neon-button/drop-vs-box-shadow.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HbWDuTEN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/neon-button/drop-vs-box-shadow.jpg" width="800" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code for &lt;code&gt;drop-shadow&lt;/code&gt; is simpler because you can attach it directly to the button.&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;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;drop-shadow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1rem&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;--purple-300&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 code for &lt;code&gt;box-shadow&lt;/code&gt; is slightly harder because you'll have to use a pseudo-element to make smooth animation. That's because transitioning &lt;code&gt;box-shadow&lt;/code&gt; &lt;a href="https://web.dev/animations-guide/"&gt;creates jank&lt;/a&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;button&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;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;content&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;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="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;inset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt; &lt;span class="m"&gt;0.5em&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;--purple-300&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;h2&gt;
  
  
  A nice zoom effect
&lt;/h2&gt;

&lt;p&gt;The third and final piece is to jell everything together with a little bit of animations.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/L-89PGVLxLo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Here, I opted to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change the &lt;code&gt;background-color&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Change the &lt;code&gt;color&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Make the button bigger (as if it's floating outwards)&lt;/li&gt;
&lt;li&gt;And make the background glow a little bit stronger by changing the &lt;code&gt;opacity&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Codepen Link
&lt;/h2&gt;

&lt;p&gt;Here's Codepen for you to play around with this &lt;a href="https://codepen.io/zellwk/pen/poQMqvW"&gt;neon button&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the way, this article is originally written on my &lt;a href="https://zellwk.com/blog/neon-button/"&gt;blog&lt;/a&gt;&lt;/strong&gt;. Feel free to visit that if you want to have these articles delivered to your email first-hand whenever they're released! 🙂.&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>Splendid Astro Spacing — A Tailwind Utility for Astro</title>
      <dc:creator>Zell Liew 🤗</dc:creator>
      <pubDate>Tue, 03 Oct 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zellwk/splendid-astro-spacing-a-tailwind-utility-for-astro-f0</link>
      <guid>https://dev.to/zellwk/splendid-astro-spacing-a-tailwind-utility-for-astro-f0</guid>
      <description>&lt;p&gt;When using Tailwind with Astro, you’ll notice that &lt;a href="https://tailwindcss.com/docs/space"&gt;Tailwind’s space utilities&lt;/a&gt; stop working when you use it with Astro Components or Slots .&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;!-- Doesn't work when using with Astro components and slots --&amp;gt;
&amp;lt;div class='space-y-4'&amp;gt;
  &amp;lt;Component client:load /&amp;gt;
  &amp;lt;Component client:load /&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason is simple. I’ve wrote about the cause in &lt;a href="https://dev.to/blog/overcoming-astro-styling-frustrations"&gt;a previous article&lt;/a&gt; and how to fix it.&lt;/p&gt;

&lt;p&gt;You can read that article for more information, but the gist is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Astro components and slots wrap it’s contents in a div that has &lt;code&gt;display: contents&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;* + *&lt;/code&gt; selector, which Tailwind uses for its space utilities, cannot target the elements within these Astro components and slots&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A simple fix
&lt;/h2&gt;

&lt;p&gt;Fixing this is simple. We just have to modify Tailwind’s space utilities with a plugin — so they can dive one level beyond Astro’s components and slots.&lt;/p&gt;

&lt;p&gt;I’ve created this plugin and added it as part of Splendid UI. You can install it Splendid UI like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;splendid-ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can use the plugin in your Tailwind config file like this:&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;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;splendid-ui/tailwind/plugins/astro-space.cjs&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(I know the path looks long and complicated right now. It's something I'll simplify in the future as Splendid UI becomes more mature. For now, just enjoy something that works! 🙃).&lt;/p&gt;

&lt;p&gt;That’s it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://splendid-ui.com"&gt;Splendid UI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;Astro Space Utility documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;By the way, this article is originally written on my &lt;a href="https://zellwk.com/blog/tailwind-space-in-astro/"&gt;blog&lt;/a&gt;&lt;/strong&gt;. Feel free to visit that if you want to have these articles delivered to your email first-hand whenever they're released! 🙂.&lt;/p&gt;

</description>
      <category>node</category>
      <category>caching</category>
      <category>splendidui</category>
    </item>
    <item>
      <title>Easy caching on the local file system with Node</title>
      <dc:creator>Zell Liew 🤗</dc:creator>
      <pubDate>Tue, 26 Sep 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zellwk/easy-caching-on-the-local-file-system-with-node-2e6c</link>
      <guid>https://dev.to/zellwk/easy-caching-on-the-local-file-system-with-node-2e6c</guid>
      <description>&lt;p&gt;Today I want to introduce you a utility that will make caching in the local file system extremely easy.&lt;/p&gt;

&lt;p&gt;This utility is called &lt;code&gt;fileCache&lt;/code&gt; and it’s built into &lt;a href="https://splendid-ui.com"&gt;Splendid UI&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;splendid-ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use the utility, import &lt;code&gt;fileCache&lt;/code&gt; from Splendid UI.&lt;/p&gt;

&lt;p&gt;Give it a directory and a file name.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The directory determines where to store the cached file.&lt;/li&gt;
&lt;li&gt;The file name determines the name of the file.
&lt;/li&gt;
&lt;/ul&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;fileCache&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;splendid-ui/node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fileCache&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;file&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;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json`&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;When you want to save values into the cache, just use the save method. Values will automatically be converted into JSON.&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;const&lt;/span&gt; &lt;span class="nx"&gt;objectToSave&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;some&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;objectToSave&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you want to load the cache, use the load method. This method returns a promise.&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;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Invalidating the cache
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fileCache&lt;/code&gt; returns the file's &lt;code&gt;modifiedAt&lt;/code&gt; timestamp. If you're familiar with Node, this is the &lt;code&gt;mstimeMs&lt;/code&gt; value you get from &lt;code&gt;fs.stat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can use this &lt;code&gt;modifiedAt&lt;/code&gt; timestamp to check whether you want to invalidate the cache.&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;getValues&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;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fileCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;Date&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;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// Load the cache&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;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modifiedAt&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10000&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;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Otherwise, create the cache&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;some&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&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;obj&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Invalidating the cache when other files change
&lt;/h3&gt;

&lt;p&gt;It's more common for cache files to be created with the content from other files. In this case, if these source files change, you will want to invalidate the cache.&lt;/p&gt;

&lt;p&gt;It's easy to do this with the &lt;a href=""&gt;&lt;code&gt;getLastModifiedTime&lt;/code&gt;&lt;/a&gt; utility from Splendid UI.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;getLastModifiedTime&lt;/code&gt; returns the last modified time from a list of files. You can use this to decide whether to invalidate the cache.&lt;/p&gt;

&lt;p&gt;It takes in a glob value so you can specify all the files you want to check. This process is extremely quick so you don't have to worry about checking lots of files at once.&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;getLastModifiedTime&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;splendid-ui/node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Gets the latest modified timestamp of all the files in src/content&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastModified&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;getLatestModifiedTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/content/**/*&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 the latest modified timestamp exceeds that of the cache, you can invalidate the cache and generate a new one.&lt;/p&gt;

&lt;p&gt;The process looks like this:&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;fileCache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getLastModifiedTime&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;splendid-ui/node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getContent&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;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fileCache&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="cm"&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;lastModified&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;getLatestModifiedTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`src/content/`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Load the cache&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;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modifiedAt&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;lastModified&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;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Otherwise, create the cache&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;some&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&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;obj&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;p&gt;Check out the documentation for &lt;code&gt;fileCache&lt;/code&gt; and &lt;code&gt;getLatestModifiedTime&lt;/code&gt; for more information.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;fileCache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;getLatestModifiedTime&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lastly, if you enjoyed this, you may also enjoy the utilities I've put together in &lt;a href="https://splendid-ui.com"&gt;Splendid UI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the way, this article is originally written on my &lt;a href="https://zellwk.com/blog/caching-in-node/"&gt;blog&lt;/a&gt;&lt;/strong&gt;. Feel free to visit that if you want to have these articles delivered to your email first-hand whenever they're released! 🙂.&lt;/p&gt;

</description>
      <category>node</category>
      <category>caching</category>
      <category>splendidui</category>
    </item>
    <item>
      <title>zlFetch now supports FormData!</title>
      <dc:creator>Zell Liew 🤗</dc:creator>
      <pubDate>Tue, 19 Sep 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zellwk/zlfetch-now-supports-formdata-15e3</link>
      <guid>https://dev.to/zellwk/zlfetch-now-supports-formdata-15e3</guid>
      <description>&lt;p&gt;"Now" is grossly inaccurate because &lt;code&gt;zlFetch&lt;/code&gt; has supported Form Data since v5.0 (since April) and we’re already at v6.0 🙃.&lt;/p&gt;

&lt;p&gt;Nevertheless, let me share with you what this is all about.&lt;/p&gt;

&lt;h2&gt;
  
  
  How &lt;code&gt;zlFetch&lt;/code&gt; supports Form Data
&lt;/h2&gt;

&lt;p&gt;You can now pass Form Data content into &lt;a href="https://github.com/zellwk/zl-fetch"&gt;&lt;code&gt;zlFetch&lt;/code&gt;&lt;/a&gt; and it will correctly send a &lt;code&gt;multipart/form-data&lt;/code&gt; encoding to the server.&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;form&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;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&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;const&lt;/span&gt; &lt;span class="nx"&gt;data&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;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;zlFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;some-url&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="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&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;This is similar to the rest of our API where &lt;code&gt;zlFetch&lt;/code&gt; automatically helps you set the &lt;code&gt;Content-Type&lt;/code&gt; header:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you pass in an object, it converts the data into JSON and sends an &lt;code&gt;application/json&lt;/code&gt; content type.&lt;/li&gt;
&lt;li&gt;If you pass in a string, it uses the &lt;code&gt;application/x-www-form-urlencoded&lt;/code&gt; content type.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Problems with Form Data
&lt;/h2&gt;

&lt;p&gt;I’m not a fan of using Form Data because of two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The backend needs to support it&lt;/li&gt;
&lt;li&gt;You can’t tell what’s inside a Form Data easily&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The backend needs to support it
&lt;/h3&gt;

&lt;p&gt;Form Data is more complicated than &lt;code&gt;json&lt;/code&gt; or &lt;code&gt;x-www-form-urlencoded&lt;/code&gt; data because it can be sent in multiple parts.&lt;/p&gt;

&lt;p&gt;In express, you can support Form Data by adding the &lt;code&gt;multer&lt;/code&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;multer&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;multer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of the time, I prefer to send JSON since there's no need to use &lt;code&gt;multer&lt;/code&gt; and mess with &lt;code&gt;multipart/form-data&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  It’s harder to debug Form Data
&lt;/h3&gt;

&lt;p&gt;You can’t see what’s inside a Form Data easily. If you want to see the contents, you have to loop through the form data and log each entry.&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;const&lt;/span&gt; &lt;span class="nx"&gt;data&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;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&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;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&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="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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--umpW9kC_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/http://zellwk.com/images/blog/zl-fetch-form-data/logging-form-data.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--umpW9kC_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/http://zellwk.com/images/blog/zl-fetch-form-data/logging-form-data.png" width="698" height="106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is way too complex for my liking. I prefer to use an Object and see everything at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Converting Form Data into an object
&lt;/h2&gt;

&lt;p&gt;Because I like working with objects more than Form Data, I included a utility in &lt;code&gt;zlFetch&lt;/code&gt; that lets you convert Form Data into an object.&lt;/p&gt;

&lt;p&gt;With this, you no longer need to extract each form element individually. Just use the utility and it’ll handle the data for you.&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="nx"&gt;zlFetch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;toObject&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;zl-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;form&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;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&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;const&lt;/span&gt; &lt;span class="nx"&gt;formData&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;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;toObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&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;data&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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nuzWR0Z6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/zl-fetch-form-data/logging-to-object.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nuzWR0Z6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/zl-fetch-form-data/logging-to-object.png" width="704" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can then send this data as JSON over to the server like this:&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="nx"&gt;zlFetch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;toObject&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;zl-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;form&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;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&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;const&lt;/span&gt; &lt;span class="nx"&gt;formData&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;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;toObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;zlFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;some-url&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="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&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 also added this utility into &lt;a href="https://splendid-ui.com"&gt;Splendid UI&lt;/a&gt; 🙃. So you can tell that I’m putting lots of helpful things into Splendid UI as I go along.&lt;/p&gt;

&lt;p&gt;It’s gonna be one of the best component libraries around. I’ll share more about Splendid in another post.&lt;/p&gt;

&lt;p&gt;Speaking about utilities, I've created another utility to it easy to send &lt;code&gt;form-urlencoded&lt;/code&gt; data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utility for form-urlencoded data
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;zlFetch&lt;/code&gt; contains a &lt;code&gt;toQueryString&lt;/code&gt; utility that can convert an object into a query string.&lt;/p&gt;

&lt;p&gt;This makes it easy to send &lt;code&gt;x-www-form-urlencoded&lt;/code&gt; data.&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;toQueryString&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;zl-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;zlFetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;some-url&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="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toQueryString&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Good game&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Behind the scenes, this is a simple utility since we're just passing the object through &lt;code&gt;URLSearchParams&lt;/code&gt; 🙃. But hey, it's good to have this utility since it makes things a little bit simpler than before!&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;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;toQueryString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&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;searchParams&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;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&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;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&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;That's it for today!&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Check &lt;code&gt;zlFetch&lt;/code&gt;'s &lt;a href="https://github.com/zellwk/zl-fetch"&gt;documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Get 2 chapters of my &lt;a href="https://magicaldevschool.com/courses/mastering-async-js"&gt;Async JS course&lt;/a&gt; for free and become fluent in AJAX.&lt;/li&gt;
&lt;li&gt;See how &lt;a href="https://splendid-ui.com"&gt;Splendid UI&lt;/a&gt; makes web development much easier for you and me!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;By the way, this article is originally written on my &lt;a href="https://zellwk.com/blog/zl-fetch-form-data/"&gt;blog&lt;/a&gt;&lt;/strong&gt;. Feel free to visit that if you want to have these articles delivered to your email first-hand whenever they're released! 🙂.&lt;/p&gt;

</description>
      <category>zlfetch</category>
      <category>node</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Limitations of Scoped CSS</title>
      <dc:creator>Zell Liew 🤗</dc:creator>
      <pubDate>Tue, 12 Sep 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zellwk/limitations-of-scoped-css-2fin</link>
      <guid>https://dev.to/zellwk/limitations-of-scoped-css-2fin</guid>
      <description>&lt;p&gt;I was really excited about Scoped CSS a couple of years back when frameworks like React and Vue introduced them.&lt;/p&gt;

&lt;p&gt;As I began trying Scoped CSS out for myself, I was disappointed and I felt it didn't live up to its hype.&lt;/p&gt;

&lt;p&gt;But after more tries, I'm happy to announce that Scoped CSS is indeed useful. You only have to realize what its limitations are and what to do when you face these limitations.&lt;/p&gt;

&lt;h2&gt;
  
  
  I’m not talking about the native CSS :scope
&lt;/h2&gt;

&lt;p&gt;Before you continue further, I want to make sure we’re talking about the same thing.&lt;/p&gt;

&lt;p&gt;In this article, I’m talking about Scoped CSS that can be found in major frameworks like React, Vue, Svelte, and Astro.&lt;/p&gt;

&lt;p&gt;I’m not talking about the native CSS &lt;code&gt;:scope&lt;/code&gt;. You can find out more about that &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:scope"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The premise of Scoped CSS
&lt;/h2&gt;

&lt;p&gt;Scoped CSS was one of the biggest features that frameworks provided us with. It promises to restrict the scope of your CSS, so your CSS would not leak into other components.&lt;/p&gt;

&lt;p&gt;The limitations of Scoped CSS are…&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You cannot style children components&lt;/li&gt;
&lt;li&gt;You cannot style slot content&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now let’s see what I mean by these limitations.&lt;/p&gt;

&lt;h2&gt;
  
  
  You cannot style children components
&lt;/h2&gt;

&lt;p&gt;From my experience, Scoped CSS in all frameworks behaves in the same manner. So I'm going to use Svelte here to illustrate my point.&lt;/p&gt;

&lt;p&gt;Let's say I imported a &lt;code&gt;SVG&lt;/code&gt; component and I'd like to style the SVG from a &lt;code&gt;Menu&lt;/code&gt; component.&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;
  import SVG from './SVG.svelte'
&amp;lt;/script&amp;gt;

&amp;lt;div class="Menu"&amp;gt;
  &amp;lt;SVG /&amp;gt;
  &amp;lt;span&amp;gt;Menu&amp;lt;/span&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;SVG&lt;/code&gt; component simply contains the SVG and nothing more.&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;!-- SVG component --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;svg&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I try to style the SVG from the &lt;code&gt;Menu&lt;/code&gt; component, the styles will not be applied.&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;!-- Menu component --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.Menu&lt;/span&gt; &lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;stroke&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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w5UJKUVB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/limitations-of-scoped-css/black-menu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w5UJKUVB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/limitations-of-scoped-css/black-menu.png" width="241" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And I'm forced to use the &lt;code&gt;global&lt;/code&gt; or the &lt;code&gt;global&lt;/code&gt; selector to style this SVG.&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;!-- Global attribute --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.Menu&lt;/span&gt; &lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;fill&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;span class="c"&gt;&amp;lt;!-- Global selector --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nd"&gt;:global&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.Menu&lt;/span&gt; &lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;fill&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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Efj0ECSi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/limitations-of-scoped-css/red-menu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Efj0ECSi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/limitations-of-scoped-css/red-menu.png" width="229" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Global Attribute
&lt;/h3&gt;

&lt;p&gt;The global attribute negates scoped CSS and allows the entire style block to act like Normal CSS.&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;style global&amp;gt;
  .Menu svg path {
    fill: red;
  }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;global&lt;/code&gt; attribute isn't a great practice because you might as well write Normal CSS instead.&lt;/p&gt;

&lt;p&gt;By the way, if you use Astro, the &lt;code&gt;global&lt;/code&gt; attribute is a directive and not an attribute.&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;style &lt;/span&gt;&lt;span class="na"&gt;is:global&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="err"&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;h3&gt;
  
  
  The Global Selector
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;:global()&lt;/code&gt; selector allows you to expose the values wrapped inside it to the global scope.&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;style&amp;gt;&lt;/span&gt;
  &lt;span class="nd"&gt;:global&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.Menu&lt;/span&gt; &lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;fill&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;If you want to keep &lt;code&gt;.Menu&lt;/code&gt; in the local scope, you can use &lt;code&gt;:global&lt;/code&gt; only on the rest of the selectors.&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;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.Menu&lt;/span&gt; &lt;span class="nd"&gt;:global&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;fill&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;This is nice.&lt;/p&gt;

&lt;p&gt;But there's a huge problem.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;global&lt;/code&gt; selector cannot be used in the middle of the selector chain. So this doesn't work.&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;style&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;/* These don’t work */&lt;/span&gt;
  &lt;span class="nc"&gt;.Menu&lt;/span&gt; &lt;span class="nd"&gt;:global&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&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;Because the &lt;code&gt;global&lt;/code&gt; selector cannot be used in the middle of the selector chain, nesting doesn't work as well.&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;style &lt;/span&gt;&lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"“scss”"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;/* This doesn’t work */&lt;/span&gt;
  &lt;span class="nc"&gt;.Menu&lt;/span&gt; &lt;span class="nd"&gt;:global&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;path&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&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 gives Scoped CSS a big minus point in my world.&lt;/p&gt;

&lt;h2&gt;
  
  
  You cannot style slot content
&lt;/h2&gt;

&lt;p&gt;Scoped CSS is also limited when you have to style slot content.&lt;/p&gt;

&lt;p&gt;For this, let's say we have an &lt;code&gt;&amp;lt;Article&amp;gt;&lt;/code&gt; component and we are going to pass the contents through a &lt;code&gt;&amp;lt;slot&amp;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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"Article"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll use &lt;code&gt;&amp;lt;Article&amp;gt;&lt;/code&gt; 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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Article&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;./Article.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;This is a header&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is a paragraph&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you try to style the slot content from &lt;code&gt;Article&lt;/code&gt; with Scoped CSS, you'll realize it doesn't work.&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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"Article"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;h2&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;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&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;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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sqE3kNRk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/limitations-of-scoped-css/black-article.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sqE3kNRk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/limitations-of-scoped-css/black-article.png" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You need to use the &lt;code&gt;global&lt;/code&gt; attribute or the &lt;code&gt;global&lt;/code&gt; selector instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Styling Slot Content
&lt;/h3&gt;

&lt;p&gt;You can use &lt;code&gt;global&lt;/code&gt; selectors or the global &lt;code&gt;attribute&lt;/code&gt; to style slot content.&lt;/p&gt;

&lt;p&gt;In this case, let's go with &lt;code&gt;global&lt;/code&gt; selectors.&lt;/p&gt;

&lt;p&gt;Here's how I would style the slot content.&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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"Article"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"scss"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;article&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;:global(h2)&lt;/span&gt; &lt;span class="err"&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;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;:global&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="o"&gt;)&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="err"&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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kb3YcGYp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/limitations-of-scoped-css/colored-article.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kb3YcGYp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/limitations-of-scoped-css/colored-article.png" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you use &lt;code&gt;global&lt;/code&gt; selectors to style slot content, pay attention to these points:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One&lt;/strong&gt;: &lt;code&gt;global&lt;/code&gt; must be written for every selector you wish to target. If you have to use a large number of &lt;code&gt;global&lt;/code&gt; selectors, it may be worthwhile to write normal CSS instead:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two&lt;/strong&gt;: &lt;code&gt;:global&lt;/code&gt; should come AFTER a selector (&lt;code&gt;article&lt;/code&gt; in this case). If &lt;code&gt;:global&lt;/code&gt; doesn't come after a selector, you'll be writing CSS into the global scope which is probably not what you want.&lt;/p&gt;

&lt;p&gt;If you did what I just mentioned, your selectors should look somewhat like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e4th97_B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/limitations-of-scoped-css/scoped-selector.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e4th97_B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/limitations-of-scoped-css/scoped-selector.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Scoped CSS is a great future.&lt;/p&gt;

&lt;p&gt;Scoped CSS can be frustrating to use when you don't know what its limitations are.&lt;/p&gt;

&lt;p&gt;Once you know the limitations, you will be able to use Scoped CSS to its fullest potential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://zellwk.com/blog/camelcss/"&gt;Camelcase CSS&lt;/a&gt; — this explains why I used title case for CSS classes.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://geoffrich.net/posts/svelte-scoped-styles/"&gt;How Svelte scopes component styles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.astro.build/en/guides/styling/#scoped-styles-1"&gt;Scoped Styles in Astro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:scope"&gt;Native CSS &lt;code&gt;:scope&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;By the way, this article is originally written on my &lt;a href="https://zellwk.com/blog/limitations-of-scoped-css/"&gt;blog&lt;/a&gt;&lt;/strong&gt;. Feel free to visit that if you want to have these articles delivered to your email first-hand whenever they're released! 🙂.&lt;/p&gt;

</description>
      <category>css</category>
      <category>astro</category>
      <category>svelte</category>
    </item>
    <item>
      <title>Quality of life improvements for zlFetch</title>
      <dc:creator>Zell Liew 🤗</dc:creator>
      <pubDate>Tue, 05 Sep 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zellwk/quality-of-life-improvements-for-zlfetch-52h0</link>
      <guid>https://dev.to/zellwk/quality-of-life-improvements-for-zlfetch-52h0</guid>
      <description>&lt;p&gt;(Hey, we're having problems showing images in RSS right now, so if you want a better reading experience, consider viewing this article online &lt;a href="https://zellwk.com//blog/zl-fetch-improvements.%20We%20hope%20to%20fix%20this%20soon!"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I silently updated &lt;code&gt;zlFetch&lt;/code&gt; a couple of months ago with some improvements that make coding much easier — especially if you're using &lt;code&gt;zlFetch&lt;/code&gt; in Node.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is zlFetch?
&lt;/h2&gt;

&lt;p&gt;Just in case you don't know about it, &lt;a href="https://github.com/zellwk/zl-fetch"&gt;zlFetch&lt;/a&gt; is a wrapper over the native Fetch API. I've built &lt;code&gt;zlFetch&lt;/code&gt; because I wanted to make it easier to use the Fetch API.&lt;/p&gt;

&lt;p&gt;Now without further ado, let me talk about the quality of life improvements I've made recently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Returning errors
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;zlFetch&lt;/code&gt; was built to catch and throw HTTP errors, so &lt;code&gt;zlFetch&lt;/code&gt; is promise-friendly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;zlFetch('some-url')
  .then(/* do something when successful */)
  .catch(/* throw an error when unsuccessful */)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although this pattern follows the promise spec, it can be very unwieldy when used in an &lt;code&gt;async&lt;/code&gt; function. Typically, if you want to handle an error, you have to use a &lt;code&gt;try/catch&lt;/code&gt;pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;try {
  const response = await zlFetch('some-url')
  // Do something with the response
} catch (error) {
  // Do something with the error
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I didn't like this so I added a &lt;code&gt;returnError&lt;/code&gt; property to &lt;code&gt;zlFetch&lt;/code&gt;. This allows you to return the error message instead of throwing it.&lt;/p&gt;

&lt;p&gt;Then you can use a standard &lt;code&gt;if/else&lt;/code&gt; conditionals to write your Fetch requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { response, error } = await zlFetch('some-url', {
  returnError: true
})

if (response) // Do something with response
if (error) // Do something with error

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can make it even easier by creating an instance of zlFetch with the options you want to use. More on this later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debug Mode
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;zlFetch&lt;/code&gt; now contains a &lt;code&gt;debug&lt;/code&gt; mode.&lt;/p&gt;

&lt;p&gt;This lets you know exactly what you're sending in your request — so you don't have to check the Network Panel to know what you sent over.&lt;/p&gt;

&lt;p&gt;Just add the &lt;code&gt;debug&lt;/code&gt; mode and you can log what you're sending over.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { response, debug } = await zlFetch(
  'https://api.github.com/users/zellwk/repos',
  {
    query: { per_page: 100 },
    debug: true,
  }
)

console.log(debug)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a zlFetch Instance
&lt;/h2&gt;

&lt;p&gt;It's now possible to create a &lt;code&gt;zlFetch&lt;/code&gt; instance that contains the options you wish to use.&lt;/p&gt;

&lt;p&gt;You can attach a base URL you wish to use over a couple of APIs...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createZlFetch } from 'zl-fetch'

// Create the instance
const api = createZlFetch('https://your-api.com/api/v1')

// Using the instance
const response = await api.post('users', {
  body: {
    firstName: 'Zell',
    lastName: 'Liew',
    email: 'helloworld@gmail.com',
  },
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...attach options you typically use...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createZlFetch } from 'zl-fetch'

// Create the instance
const api = createZlFetch({ returnError: true })

// Using the instance
const { response, error } = await api.post(/* ... */)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... or both!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createZlFetch } from 'zl-fetch'

// Create the instance
const api = createZlFetch('https://your-api.com/api/v1', {
  returnError: true,
})

// Using the instance
const { response, error } = await api.post('users', {
  body: {
    firstName: 'Zell',
    lastName: 'Liew',
    email: 'helloworld@gmail.com',
  },
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This feature helps a lot when you have to send many fetch requests in the same file.&lt;/p&gt;

&lt;p&gt;One great example is if you create a file to house all requests to a particular API.&lt;/p&gt;

&lt;p&gt;Another great example is when you have to send many requests when you test your APIs. (I cover this in more detail in my &lt;a href="https://magicaldevschool.com/workshops"&gt;Node Workshop&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Removing node-fetch as a dependency.
&lt;/h2&gt;

&lt;p&gt;We have removed the &lt;code&gt;node-fetch&lt;/code&gt; dependency in &lt;code&gt;v6.0.0&lt;/code&gt; since Node &lt;code&gt;v17&lt;/code&gt; contains the Fetch API.&lt;/p&gt;

&lt;p&gt;You will still be able to use &lt;code&gt;zlFetch&lt;/code&gt; as normal — nothing will change — if you're using Node &lt;code&gt;v17&lt;/code&gt; and above.&lt;/p&gt;

&lt;p&gt;If you're using a legacy version of Node, we'll need you to import &lt;code&gt;node-fetch&lt;/code&gt; into your project before using &lt;code&gt;zlFetch&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  That's it for today!
&lt;/h2&gt;

&lt;p&gt;There are a few more qualify of life improvements that I've made, but I think this is big enough of an announcement today.&lt;/p&gt;

&lt;p&gt;I'll talk about other features in another newsletter to come.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the way, this article is originally written on my &lt;a href="https://zellwk.com/blog/zl-fetch-improvements/"&gt;blog&lt;/a&gt;&lt;/strong&gt;. Feel free to visit that if you want to have these articles delivered to your email first-hand whenever they're released! 🙂.&lt;/p&gt;

</description>
      <category>zlfetch</category>
      <category>node</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The Magical Dev School Student Portal is live!</title>
      <dc:creator>Zell Liew 🤗</dc:creator>
      <pubDate>Tue, 29 Aug 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zellwk/the-magical-dev-school-student-portal-is-live-b68</link>
      <guid>https://dev.to/zellwk/the-magical-dev-school-student-portal-is-live-b68</guid>
      <description>&lt;p&gt;(Hey, we're having problems showing images in RSS right now, so if you want a better reading experience, consider viewing this article online &lt;a href="https://zellwk.com//blog/mds-student-portal.%20We%20hope%20to%20fix%20this%20soon!"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ve been working on this for a long time and I’m happy to share with you that the Magical Dev School student portal is live!&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s this portal about?
&lt;/h2&gt;

&lt;p&gt;Earlier in February, I decided to put all my courses under a brand called &lt;a href="https://magicaldevschool.com"&gt;Magical Dev School&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This portal is simply a place where you can access all my courses and workshops.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b9fytlcp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0raebtd1uzvmt4jtu5sj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b9fytlcp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0raebtd1uzvmt4jtu5sj.png" alt="Image description" width="800" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to access the portal
&lt;/h2&gt;

&lt;p&gt;It’s simple. &lt;a href="https://students.magicaldevschool.com"&gt;Just go here&lt;/a&gt; and fill in your email and password.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you have purchased the Courses, Workshops, or Everything package&lt;/strong&gt; from &lt;a href="https://magicaldevschool.com/join"&gt;Magical Dev School&lt;/a&gt;, you will be able to access the corresponding items you have purchased.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you have purchased a course (like &lt;a href="https://learnjavascript.today"&gt;Learn JavaScript&lt;/a&gt;)&lt;/strong&gt; before I consolidated everything into Magical Dev School, you will also be able to use the Magical Dev School student. portal. In this case, you'll have access to the full Learn JavaScript course in the portal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You will also have access to free chapters of other courses and workshops&lt;/strong&gt; if you haven't purchased them yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Magical Dev School portal is pretty well designed
&lt;/h2&gt;

&lt;p&gt;I want to take the opportunity to share with you a few quality-of-life improvements I’ve made for you on this platform.&lt;/p&gt;

&lt;p&gt;They are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Product Switcher to jump to any course or workshop easily&lt;/li&gt;
&lt;li&gt;Breadcrumbs to show you where you’re at&lt;/li&gt;
&lt;li&gt;Assess the lesson plan from every page&lt;/li&gt;
&lt;li&gt;Estimated timestamps for each course, chapter, and lesson&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Product Switcher to jump to any course or workshop easily
&lt;/h2&gt;

&lt;p&gt;I added a product switcher in the menu so you can jump to any course or workshop easily.&lt;/p&gt;

&lt;p&gt;This is a tentative design and I may change it as the portal matures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breadcrumbs to show you where you’re at
&lt;/h2&gt;

&lt;p&gt;The second quality of life improvement is breadcrumbs that show you exactly which lesson you’re in.&lt;/p&gt;

&lt;p&gt;I added this because it’s easy to get lost in the sea of lessons we have available in Magic’s Dev School.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assess the lesson plan from every page
&lt;/h2&gt;

&lt;p&gt;If you click the book icon on the breadcrumbs, you will be able to access the lesson plan for the entire course you’re viewing.&lt;/p&gt;

&lt;p&gt;This will help you get a good grasp of where you’re at in the entire course.&lt;/p&gt;

&lt;p&gt;You’ll also be able to jump to another lesson easily if you wish to backtrack or skip forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Estimated timestamps for each course, chapter, and lesson
&lt;/h2&gt;

&lt;p&gt;Last but not least, I have added estimated timestamps to all courses, chapters, and lessons.&lt;/p&gt;

&lt;p&gt;This should give you an idea of how much content there is in each course, chapter, and lesson, and therefore, how much time you may have to spend.&lt;/p&gt;

&lt;p&gt;Note that these are just estimated reading/video times! You’ll likely spend way more time than the stated values since you may have to go through some lessons multiple times.&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s it from me this week!
&lt;/h2&gt;

&lt;p&gt;Hope you enjoy our new &lt;a href="https://students.magicaldevschool.com"&gt;course portal&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;If you have any questions, just reach out and I’ll get back to you as soon as I can.&lt;/p&gt;

&lt;p&gt;By the way, this article is originally written on my &lt;a href="https://zellwk.com/blog/mds-student-portal/"&gt;blog&lt;/a&gt;. Feel free to visit that if you want to have these articles delivered to your email first-hand whenever they're released! 🙂.&lt;/p&gt;

</description>
      <category>productupdates</category>
    </item>
    <item>
      <title>Finding my roots in my business</title>
      <dc:creator>Zell Liew 🤗</dc:creator>
      <pubDate>Tue, 22 Aug 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zellwk/finding-my-roots-in-my-business-2hb1</link>
      <guid>https://dev.to/zellwk/finding-my-roots-in-my-business-2hb1</guid>
      <description>&lt;p&gt;(Hey, we're having problems showing images in RSS right now, so if you want a better reading experience, consider viewing this article online &lt;a href="https://zellwk.com//blog/finding-my-roots.%20We%20hope%20to%20fix%20this%20soon!"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ve pretended to be happy, okay, upbeat, and positive in my communications with you in the last couple of months.&lt;/p&gt;

&lt;p&gt;Occasionally, I have also become cunning, manipulative, and sleazy in my communications (and I loathed that).&lt;/p&gt;

&lt;p&gt;The discomfort towards my behaviours has been taking a hold of my emotional space. And it’s creating a huge depression.&lt;/p&gt;

&lt;h2&gt;
  
  
  I created this blog to document my journey and to help
&lt;/h2&gt;

&lt;p&gt;Not to do business.&lt;/p&gt;

&lt;p&gt;It’s a wonderful miracle that this blog somehow transformed into a viable business that had supported my livelihood for many years.&lt;/p&gt;

&lt;p&gt;I’m still not quite sure how it happened. But one for I do know for sure — it seems to do best when I truly try to help.&lt;/p&gt;

&lt;h2&gt;
  
  
  But this miracle led to a series of tragedies
&lt;/h2&gt;

&lt;p&gt;Twice now, I tried to go “all-in” on the business (and the blog).&lt;/p&gt;

&lt;p&gt;Both times, I became obsessive, blinded by money, and I lose my way.&lt;/p&gt;

&lt;p&gt;I would listen to gurus that tout what should be done, and I would even do some of these things that went against my conscience. (Like putting up a modal to grab emails, which obviously didn’t work with the smart crowd that I work with).&lt;/p&gt;

&lt;p&gt;And since I have pretty good stamina, I would hammer away at the “work” with determination.&lt;/p&gt;

&lt;p&gt;So far, when I do this for a prolonged period of time, I would find myself falling into depression.&lt;/p&gt;

&lt;p&gt;I would end up not wanting to work, not because I don’t enjoy working, but because I have no idea what I’m doing anymore. (And sometimes because I became too ashamed of my actions)&lt;/p&gt;

&lt;p&gt;It’s not pretty.&lt;/p&gt;

&lt;p&gt;So eventually I had to stop.&lt;/p&gt;

&lt;h2&gt;
  
  
  I hope to find back my core
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;There is a reason why I continue to teach — even though it may not be the most profitable business in the world.&lt;/li&gt;
&lt;li&gt;There is a reason why I chose to be a developer instead of a teacher — so teaching must not be everything I do.&lt;/li&gt;
&lt;li&gt;And there is a reason why I choose to run my business instead of being employed as a developer and getting a cushy pay.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So far in my journey, I have always neglected at least one of these three elements for a prolonged duration.&lt;/p&gt;

&lt;p&gt;Each time this happens, I would fall into depression too.&lt;/p&gt;

&lt;p&gt;Recently, I was lucky to have found Jon Yongfook’s blog. One of his articles spoke about the &lt;a href="https://www.bannerbear.com/blog/why-you-should-do-50-coding-and-50-marketing-as-a-solo-tech-founder/"&gt;idea of splitting time equally between marketing and coding&lt;/a&gt; as a tech founder.&lt;/p&gt;

&lt;p&gt;When I read the article, I felt that I may have just found a path out of my depression with work — hopefully permanently.&lt;/p&gt;

&lt;p&gt;So I’m planning to spend an equal amount of time doing three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Designing and coding&lt;/li&gt;
&lt;li&gt;Marketing&lt;/li&gt;
&lt;li&gt;Teaching&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I have not decided on the ratio yet. But I’m likely going to experiment with a 1:1:1 ratio (or simply just two weeks each).&lt;/p&gt;

&lt;p&gt;And I hope everything would fall back into place.&lt;/p&gt;

&lt;p&gt;That’s it from me this week. Thanks for reading and have a nice day!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the way, this article is originally written on my &lt;a href="https://zellwk.com/blog/finding-my-roots/"&gt;blog&lt;/a&gt;&lt;/strong&gt;. Feel free to visit that if you want to have these articles delivered to your email first-hand whenever they're released! 🙂.&lt;/p&gt;

</description>
      <category>musings</category>
      <category>business</category>
      <category>reflection</category>
    </item>
    <item>
      <title>Here’s how to quickly test components that use container queries</title>
      <dc:creator>Zell Liew 🤗</dc:creator>
      <pubDate>Mon, 10 Jul 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zellwk/heres-how-to-quickly-test-components-that-use-container-queries-3d32</link>
      <guid>https://dev.to/zellwk/heres-how-to-quickly-test-components-that-use-container-queries-3d32</guid>
      <description>&lt;p&gt;Container queries are amazing. They let us build UI that allow a component looks good no matter what size the component is displayed at.&lt;/p&gt;

&lt;p&gt;But this feature also makes it difficult to test container queries.&lt;/p&gt;

&lt;p&gt;If you do it normally, you have to resize your browser many times, which can be irritating and a huge waste of time.&lt;/p&gt;

&lt;p&gt;There is a better way.&lt;/p&gt;

&lt;h2&gt;
  
  
  There are two ways to make things easier
&lt;/h2&gt;

&lt;p&gt;The first is to use a browser like &lt;a href="https://polypane.app/?ref=zellwk"&gt;Polypane&lt;/a&gt; that lets you debug multiple viewports at the same time. It costs only $9/m and it has the potential to reduce a lot of developmental headaches.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zeOueFla--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/test-container-queries/polypane.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zeOueFla--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/test-container-queries/polypane.png" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you don't want to spend any money, the second way is to debug your components with a utility that lets you display the component in many different sizes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8lKlRMqY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/test-container-queries/utility.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8lKlRMqY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/test-container-queries/utility.png" width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Here's how the utility works
&lt;/h2&gt;

&lt;p&gt;The basic idea is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You create a series of containers at different widths.&lt;/li&gt;
&lt;li&gt;Then you insert the component into each container.&lt;/li&gt;
&lt;li&gt;And each container will let you see what the component looks like at that width.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You'll find the code below.&lt;/p&gt;

&lt;p&gt;I’ve written this in Astro because I currently use Astro. But this can be reworked for React, Vue, Svelte, Nunjucks, Pug, and all sorts of frameworks and template engines easily.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
let { containers, increment, startAt } = Astro.props

// Default options
containers = containers || 10 // Show 10 containers
increment = increment || 50 // Containers should increase by 50px each time by default
startAt = startAt || 300 // The smallest container is 300px wide
---

&amp;lt;div class='CQTestGrid'&amp;gt;
  {
    [...Array(containers)].map((_, i) =&amp;gt; {
      const width = i * increment + startAt + 'px'
      return (
        &amp;lt;div style={`width: ${width}`}&amp;gt;
          &amp;lt;div class='size'&amp;gt;{width}&amp;lt;/div&amp;gt;
          &amp;lt;slot /&amp;gt;
        &amp;lt;/div&amp;gt;
      )
    })
  }
&amp;lt;/div&amp;gt;

&amp;lt;style&amp;gt;
  .CQTestGrid {
    display: flex;
    flex-flow: row wrap;
    padding: 1rem;

    &amp;gt; * {
      margin: 0.5rem;
    }
  }

  .size {
    font-size: 0.8rem;
    color: #666;
  }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's how you would use the utility in an actual test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
import CQTest from '../components/CQTest.astro'

const props = {
  containers: 10,
  increment: 25,
  startAt: 100,
}
---

&amp;lt;Base&amp;gt;
  &amp;lt;CQTest {...props}&amp;gt;
    {
      [...Array(props.containers)].map(_ =&amp;gt; (
        &amp;lt;div class='“Container”'&amp;gt;Your component here&amp;lt;/div&amp;gt;
      ))
    }
  &amp;lt;/CQTest&amp;gt;
&amp;lt;/Base&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using this, I can make sure the component looks great all the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take this out for a spin! 🙃
&lt;/h2&gt;

&lt;p&gt;I hope this utility helps you reduce the problems you may face as you make the best UI you can!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the way, this article is originally written on my &lt;a href="https://zellwk.com/blog/test-components-that-use-container-queries/"&gt;blog&lt;/a&gt;&lt;/strong&gt;. Feel free to visit that if you want to have these articles delivered to your email first-hand whenever they're released! 🙂.&lt;/p&gt;

</description>
      <category>containerqueries</category>
      <category>css</category>
      <category>astro</category>
    </item>
    <item>
      <title>When building components in Astro, you might not want to use Astro files</title>
      <dc:creator>Zell Liew 🤗</dc:creator>
      <pubDate>Thu, 15 Jun 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zellwk/when-building-components-in-astro-you-might-not-want-to-use-astro-files-2elf</link>
      <guid>https://dev.to/zellwk/when-building-components-in-astro-you-might-not-want-to-use-astro-files-2elf</guid>
      <description>&lt;p&gt;"If you're using Astro, you should build components with the &lt;code&gt;astro&lt;/code&gt; extension".&lt;/p&gt;

&lt;p&gt;That was my initial thought when I started using Astro. But after a couple of months building with Astro, my thinking has changed. I no longer build most of my components with &lt;code&gt;astro&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;I mostly use Svelte files instead. This article explains why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three reasons
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Reason 1: I use Svelte as my framework of choice
&lt;/h3&gt;

&lt;p&gt;This reason is pretty obvious — I have to write Svelte files if I want to use Svelte!&lt;/p&gt;

&lt;p&gt;I chose Svelte after evaluating the major three frameworks (React, Vue, and Svelte) and I found that Svelte has a better raw developer experience.&lt;/p&gt;

&lt;p&gt;I can share more about why that’s the case, but I’ll have to do that in another blog post since that will be a long one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason 2: the main reason
&lt;/h3&gt;

&lt;p&gt;The main reason is this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Astro can import framework files.&lt;/li&gt;
&lt;li&gt;But framework files cannot import Astro files&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Many commonly used components can be written in Svelte, so it can be imported into both Astro and Svelte files.&lt;/p&gt;

&lt;p&gt;Here are some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Button component&lt;/li&gt;
&lt;li&gt;An SVG component that searches the project for an SVG icon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If build these components in Astro, we won’t be able to use them inside Svelte files — and this eventually forced me to rewrite these components in Svelte.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason 3: Better syntax
&lt;/h3&gt;

&lt;p&gt;I say better syntax because I find it easier to read Svelte markup over React’s and Vue’s markup — especially when there are if statements or loops.&lt;/p&gt;

&lt;p&gt;This might have been because I’ve been using nunjucks for a long time, so the if syntax is much easier for me to read.&lt;/p&gt;

&lt;p&gt;Sometimes I choose to write components in Svelte precisely to take advantage of this syntax difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use Astro files
&lt;/h2&gt;

&lt;p&gt;I only choose the &lt;code&gt;Astro&lt;/code&gt; file extension for my component files when I need to use Astro’s API like content collections, which is not available in other frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What if a component requires both Astro APIs and JavaScript?
&lt;/h2&gt;

&lt;p&gt;I encountered this a couple of times. When this happens, I typically do two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I build an Astro component that retrieves stuff I need with Astro’s API.&lt;/li&gt;
&lt;li&gt;And I build a Svelte component that uses this information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usually, I would give both components the same name because it helps me remember that they are directly related to each other.&lt;/p&gt;

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

&lt;p&gt;Use the following guidelines if you’re deciding which extension when we build components in Astro:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build the component in your framework of choice whenever possible&lt;/li&gt;
&lt;li&gt;Only use Astro components when you need Astro’s API (or it’s heavily file-system related)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you need both Astro’s API and JavaScript, feel free to build components with both extensions. Just remember to give them appropriate names so you know they’re related to each other!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the way, this article is originally written on my &lt;a href="https://zellwk.com/blog/building-components-in-astro/"&gt;blog&lt;/a&gt;&lt;/strong&gt;. Feel free to visit that if you want to have these articles delivered to your email first-hand whenever they're released! 🙂.&lt;/p&gt;

</description>
      <category>astro</category>
      <category>svelte</category>
    </item>
    <item>
      <title>Best practices for container queries</title>
      <dc:creator>Zell Liew 🤗</dc:creator>
      <pubDate>Wed, 07 Jun 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zellwk/best-practices-for-container-queries-506p</link>
      <guid>https://dev.to/zellwk/best-practices-for-container-queries-506p</guid>
      <description>&lt;p&gt;I've been playing around with container queries and so far, there is only one best practice that I would recommend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Whenever you use container queries, make sure you wrap the element with a container element&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So your HTML should look 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;"container"&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;"component"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; … &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt; 
&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 container should not be the element that creates a grid in your layout.&lt;/p&gt;

&lt;p&gt;So don’t do 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;'grid container'&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;"component"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; … &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt; 
&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;Do this 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;"grid"&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;"container"&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;"component"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; … &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt; 
&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;Now, all three code examples above assume you’re using an unnamed container, which is sufficient for most use cases.&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="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;container-type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-size&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;h2&gt;
  
  
  There’s a reason why we need to do this
&lt;/h2&gt;

&lt;p&gt;Most of the time, I would have preferred the second structure (where the &lt;code&gt;grid&lt;/code&gt; is also the &lt;code&gt;container&lt;/code&gt;) because I will be able to reduce the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; soup in the HTML.&lt;/p&gt;

&lt;p&gt;After all, who doesn’t love clean code?&lt;/p&gt;

&lt;p&gt;But beyond the obvious benefit (more semantic-looking HTML structure), there’s a reason why we have to use the third HTML structure which I recommend.&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;!-- There’s a reason why we need this structure --&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;"grid"&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;"container"&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;"component"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;…&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&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;
  
  
  If you use the second structure, you won’t be able to use container query units
&lt;/h2&gt;

&lt;p&gt;These units will likely be inaccurate.&lt;/p&gt;

&lt;p&gt;Consider this.&lt;/p&gt;

&lt;p&gt;If you use the second HTML structure, your &lt;code&gt;.grid&lt;/code&gt; will be the container.&lt;/p&gt;

&lt;p&gt;Since your &lt;code&gt;.grid&lt;/code&gt; is the container, container query units will be based on the height and width of the &lt;code&gt;.grid&lt;/code&gt;. This is probably not what you want, because it can produce unintended (huge) sizes like the one you see below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rSmVpKhl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/container-query-best-practice/cqi-too-large.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rSmVpKhl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/container-query-best-practice/cqi-too-large.png" alt="cqi unit produced a size that was too large." width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, I set the image to &lt;code&gt;25cqi&lt;/code&gt; — which means 25% of the width of the container.&lt;/p&gt;

&lt;p&gt;But because the &lt;code&gt;.grid&lt;/code&gt; is the container, &lt;code&gt;cqi&lt;/code&gt; draws from the width of the &lt;code&gt;.grid&lt;/code&gt; (which is almost the same as the browser viewport in this case). So &lt;code&gt;cqi&lt;/code&gt; produced an oversized image.&lt;/p&gt;

&lt;p&gt;These blunders can be prevented if we used the HTML structure I recommend — because container query units will draw its width from the grid item instead.&lt;/p&gt;

&lt;p&gt;Here’s the corrected version of what I was trying to create:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m70oFY9F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/container-query-best-practice/cqi-just-right.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m70oFY9F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/container-query-best-practice/cqi-just-right.png" alt="cqi unit produced a size that was just right." width="758" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it!&lt;/p&gt;

&lt;p&gt;This is really straightforward and I hope this article helps you prevent making some of the blunders I made when testing out container queries 🙂&lt;/p&gt;

&lt;p&gt;As to the real reason why I made this blunder… well I was simply trying to see if I could use &lt;code&gt;:has&lt;/code&gt; to automatically make the parent element a container.&lt;/p&gt;

&lt;p&gt;And from there, I encountered this error!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the way, this article is originally written on my &lt;a href="https://zellwk.com/blog/container-queries-best-practice/"&gt;blog&lt;/a&gt;&lt;/strong&gt;. Feel free to visit that if you want to have these articles delivered to your email first-hand whenever they're released! 🙂.&lt;/p&gt;

</description>
      <category>css</category>
      <category>containerqueries</category>
    </item>
    <item>
      <title>Overcoming styling frustrations caused by Astro islands and slots</title>
      <dc:creator>Zell Liew 🤗</dc:creator>
      <pubDate>Mon, 22 May 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/zellwk/overcoming-styling-frustrations-caused-by-astro-islands-and-slots-174d</link>
      <guid>https://dev.to/zellwk/overcoming-styling-frustrations-caused-by-astro-islands-and-slots-174d</guid>
      <description>&lt;p&gt;After using Astro for a while, I came to realize that Astro's biggest features — islands and slots — both delight and frustrate me.&lt;/p&gt;

&lt;p&gt;Most people already know what the delights are, so I won't bother writing about them in this article. I'll focus on what frustrates me and how I resolve those frustrations.&lt;/p&gt;

&lt;p&gt;First, we need to talk about when Astro creates islands and slots.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Astro creates islands and slots
&lt;/h2&gt;

&lt;p&gt;Astro creates an &lt;code&gt;astro-island&lt;/code&gt; tag, along with &lt;code&gt;style&lt;/code&gt; and &lt;code&gt;script&lt;/code&gt; tags when you include a component with client directives.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
import Component from './components/Component.svelte'
---

&amp;lt;Component client:load /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nGfTwmek--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/astro-island.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nGfTwmek--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/astro-island.png" width="668" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the component (with client directives) contains a &lt;code&gt;slot&lt;/code&gt;, Astro will create an &lt;code&gt;astro-slot&lt;/code&gt; tag. This &lt;code&gt;astro-slot&lt;/code&gt; will be found within an &lt;code&gt;astro-island&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;---
import Component from './components/Component.svelte'
---

&amp;lt;Component client:load&amp;gt;
  &amp;lt;div&amp;gt;Some Slotted Content&amp;lt;/div&amp;gt;
&amp;lt;/Component&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6HFYtqoP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/astro-slots.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6HFYtqoP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/astro-slots.png" width="673" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, if you include a component without client directives, Astro will not create &lt;code&gt;astro-island&lt;/code&gt; and &lt;code&gt;astro-slot&lt;/code&gt; tags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
import Component from './components/Component.svelte'
---

&amp;lt;Component&amp;gt;
  &amp;lt;div&amp;gt;Some Slotted Content&amp;lt;/div&amp;gt;
&amp;lt;/Component&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ITo9dZ7U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/no-slots.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ITo9dZ7U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/no-slots.png" width="488" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's frustrating about Astro islands and slots
&lt;/h2&gt;

&lt;p&gt;Since Astro only creates these tags when you include client directives, styling components can become unpredictable — because some components will have client directives while others won't.&lt;/p&gt;

&lt;p&gt;Problems arise when the DOM contains &lt;code&gt;astro-island&lt;/code&gt; and &lt;code&gt;astro-slots&lt;/code&gt;. That's because these tags change the document flow, so you cannot pretend that they don't exist.&lt;/p&gt;

&lt;p&gt;To be more specific, I noticed four extremely frustrating things when &lt;code&gt;astro-island&lt;/code&gt; and &lt;code&gt;astro-slot&lt;/code&gt; are present in the DOM.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Direct descendant selectors no longer work&lt;/li&gt;
&lt;li&gt;Lobotomized owls no longer work&lt;/li&gt;
&lt;li&gt;CSS Grid positioning no longer works&lt;/li&gt;
&lt;li&gt;Nth-child no longer works&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'm going to talk about each one in turn, and how to resolve these frustrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Direct descendant selectors no longer work
&lt;/h2&gt;

&lt;p&gt;Direct descendant selectors no longer work when &lt;code&gt;astro-island&lt;/code&gt; and &lt;code&gt;astro-slot&lt;/code&gt; is in the DOM.&lt;/p&gt;

&lt;p&gt;This makes sense because the DOM has changed, so direct descendant selectors no longer target the element you wish to target.&lt;/p&gt;

&lt;p&gt;Imagine you want to have this HTML&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;"Component"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Some Content&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&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;But Astro creates this HTML because it has slots.&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;"Component"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;astro-slot&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Some Content&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/astro-slot&amp;gt;&lt;/span&gt;
&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;If you wrote a direct descendant selector, that selector wouldn't work. That's because the direct descendant selector now targets the &lt;code&gt;astro-slot&lt;/code&gt; level children instead of the one you are aiming for.&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="c"&gt;/* No longer works */&lt;/span&gt;
&lt;span class="nc"&gt;.Component&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Styles here */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fixing it
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Fixing direct descendant selectors with slots is simple — all you have to do is add &lt;code&gt;astro-slot&lt;/code&gt; in the selector chain.&lt;/strong&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="c"&gt;/* Works */&lt;/span&gt;
&lt;span class="nc"&gt;.Component&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;astro-slot&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Styles here */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code snippets assume you're writing global CSS. If you're using CSS Scoped to the component, you'll have to write the following instead since we're dealing with slots.&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="c"&gt;/* Scoped CSS*/&lt;/span&gt;
&lt;span class="nc"&gt;.Component&lt;/span&gt; &lt;span class="nd"&gt;:global&lt;/span&gt;&lt;span class="o"&gt;(&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;astro-slot&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Styles here */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Another alternative is simply to use descend selectors instead of direct descendant selectors&lt;/strong&gt; if the HTML structure allows for it.&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="c"&gt;/* Works */&lt;/span&gt;
&lt;span class="nc"&gt;.Component&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Styles here */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's move on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lobotomized owls no longer work
&lt;/h2&gt;

&lt;p&gt;Lobotomized owl is a way to style things with the sibling universal selectors. &lt;a href="https://alistapart.com/article/axiomatic-css-and-lobotomized-owls/"&gt;It was first coined by Heydon Pickering&lt;/a&gt; in 2014.&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="c"&gt;/* Lobotomized owl selector */&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Your styles here */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lobotomized owl selector can be used to style children elements easily — giving them margins, paddings, and other properties as necessary.&lt;/p&gt;

&lt;p&gt;Here's an example that I commonly use to give some space between elements.&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="nc"&gt;.Parent&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&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;margin-top&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, these styles won't work on &lt;code&gt;astro-island&lt;/code&gt; and &lt;code&gt;astro-slot&lt;/code&gt; tags because they use the &lt;a href="https://bitsofco.de/how-display-contents-works/"&gt;&lt;code&gt;display: content&lt;/code&gt; property&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZqaYmpzb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/lobotomized-owl-not-working.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZqaYmpzb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/lobotomized-owl-not-working.png" width="648" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixing it
&lt;/h3&gt;

&lt;p&gt;Elements with &lt;code&gt;display: contents&lt;/code&gt; will have their styles ignored, so any styles added to these elements will be ignored.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The easy way to fix this is to add the styles to the elements contained in &lt;code&gt;astro-island&lt;/code&gt; or &lt;code&gt;astro-slot&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's what the CSS looks like.&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="nc"&gt;.Parent&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;*,&lt;/span&gt;
&lt;span class="nc"&gt;.Parent&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nd"&gt;:where&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;astro-island&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;astro-slot&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;:first-child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GfQY2yMr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/lobotomized-owl-working.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GfQY2yMr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/lobotomized-owl-working.png" width="647" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS Grid Positioning no longer works
&lt;/h2&gt;

&lt;p&gt;This one is similar to the lobotomized owl one — because Astro islands and slots use &lt;code&gt;display: contents&lt;/code&gt;, no styles will work on them.&lt;/p&gt;

&lt;p&gt;These styles include &lt;code&gt;grid-column&lt;/code&gt;, &lt;code&gt;grid-row&lt;/code&gt;. So you will not be able to change the Conponent's positioning with &lt;code&gt;grid-column&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's an example where we laid all items out in a two-column grid. In this example, trying to use set &lt;code&gt;grid-column&lt;/code&gt; on the &lt;code&gt;astro-island&lt;/code&gt; and &lt;code&gt;astro-slots&lt;/code&gt; will not work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
import Component from './Component.svelte'
---

&amp;lt;div class='Grid'&amp;gt;
  &amp;lt;Component client:load /&amp;gt;
  &amp;lt;Component client:load /&amp;gt;
  &amp;lt;Component client:load /&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;style&amp;gt;
  .Grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1em;
  }

  /* Tries to make all grid items span the full width */
  .Grid &amp;gt; * {
    grid-column: 1 / -1;
  }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yd6L_ZL4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/grid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yd6L_ZL4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/grid.png" width="650" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two ways to fix this problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixing it
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The first way is to bypass &lt;code&gt;astro-island&lt;/code&gt; and &lt;code&gt;astro-slot&lt;/code&gt; with the technique mentioned abov&lt;/strong&gt;e.&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="nc"&gt;.grid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Tries to make all grid items span the full width */&lt;/span&gt;
&lt;span class="nc"&gt;.grid&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*,&lt;/span&gt;
&lt;span class="nc"&gt;.grid&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;:where&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;astro-island&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;astro-slot&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;:first-child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;grid-column&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;-1&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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vz46rNE5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/grid-fixed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vz46rNE5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/grid-fixed.png" width="657" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The second way is to put the components in another element.&lt;/strong&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;class=&lt;/span&gt;&lt;span class="s"&gt;"Grid"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;Component&lt;/span&gt; &lt;span class="na"&gt;client:load&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&amp;gt;&amp;lt;Component&lt;/span&gt; &lt;span class="na"&gt;client:load&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&amp;gt;&amp;lt;Component&lt;/span&gt; &lt;span class="na"&gt;client:load&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&amp;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 css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.Grid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.Grid&lt;/span&gt; &lt;span class="o"&gt;&amp;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;grid-column&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;-1&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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vz46rNE5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/grid-fixed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vz46rNE5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/grid-fixed.png" width="657" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Nth-child no longer works as expected
&lt;/h2&gt;

&lt;p&gt;When Astro adds &lt;code&gt;astro-island&lt;/code&gt; to the DOM, they also add &lt;code&gt;style&lt;/code&gt;and &lt;code&gt;script&lt;/code&gt; tags to the DOM at the same time.&lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;style&lt;/code&gt; and &lt;code&gt;script&lt;/code&gt; tags are also considered children elements, you cannot depend on the &lt;code&gt;nth-child&lt;/code&gt; selector to target the right element anymore.&lt;/p&gt;

&lt;p&gt;Using the same code examples from above, let's say we have the following HTML.&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;"Grid"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Component&lt;/span&gt; &lt;span class="na"&gt;client:load&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/Component&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Component&lt;/span&gt; &lt;span class="na"&gt;client:load&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/Component&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Component&lt;/span&gt; &lt;span class="na"&gt;client:load&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/Component&amp;gt;&lt;/span&gt;
&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 produces a DOM that looks like this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First element is a &lt;code&gt;style&lt;/code&gt; tag&lt;/li&gt;
&lt;li&gt;Second element is a &lt;code&gt;script&lt;/code&gt; tag&lt;/li&gt;
&lt;li&gt;Next three elements are &lt;code&gt;astro-island&lt;/code&gt; tags&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--feWk4BhI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/astro-components.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--feWk4BhI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/astro-components.png" width="724" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Astro will only include &lt;code&gt;style&lt;/code&gt; and &lt;code&gt;script&lt;/code&gt; tags for the components once in the DOM. This is why you see only one &lt;code&gt;style&lt;/code&gt; tag and one &lt;code&gt;script&lt;/code&gt; instead of 3 &lt;code&gt;style&lt;/code&gt; tags and 3 &lt;code&gt;script&lt;/code&gt; tags.&lt;/p&gt;

&lt;p&gt;If you want to get the first component with &lt;code&gt;nth-child&lt;/code&gt;, you need to pass in &lt;code&gt;nth-child(3)&lt;/code&gt; instead of &lt;code&gt;nth-child(1)&lt;/code&gt;. That's because the first component is now the third element in the DOM tree.&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="c"&gt;/* Style the first component, but it's the third child */&lt;/span&gt;
&lt;span class="nc"&gt;.Grid&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;:nth-child&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.Component&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w3tM2RBY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/component-red.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w3tM2RBY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/component-red.png" width="652" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, I know it's confusing.&lt;/p&gt;

&lt;p&gt;There are two ways to fix this confusing problem&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixing it
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The first way is to wrap the components with another element.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can then use &lt;code&gt;nth-child&lt;/code&gt; to style with a descendant selector to style the 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;"Grid"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;Component&lt;/span&gt; &lt;span class="na"&gt;client:load&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&amp;gt;&amp;lt;Component&lt;/span&gt; &lt;span class="na"&gt;client:load&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&amp;gt;&amp;lt;Component&lt;/span&gt; &lt;span class="na"&gt;client:load&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&amp;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 css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Tries to make all grid items span the full width */&lt;/span&gt;
&lt;span class="nc"&gt;.Grid&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;:first-child&lt;/span&gt; &lt;span class="nc"&gt;.Component&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w3tM2RBY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/component-red.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w3tM2RBY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/component-red.png" width="652" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The second way is to stop using &lt;code&gt;nth-child&lt;/code&gt; and use &lt;code&gt;nth-of-type&lt;/code&gt; instead.&lt;/strong&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="nc"&gt;.Grid&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;astro-island&lt;/span&gt;&lt;span class="nd"&gt;:nth-of-type&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.Component&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w3tM2RBY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/component-red.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w3tM2RBY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/component-red.png" width="652" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A deeper layer of frustrations
&lt;/h2&gt;

&lt;p&gt;Things get a little bit more confusing if you need to pass a component into a slot — especially if both components (the parent one and the one in the slot) need JavaScript functionality.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
import Component from './components/Component.svelte'
import Nested from './components/Nested.svelte'
---

&amp;lt;Component client:load&amp;gt;
  &amp;lt;Nested client:load /&amp;gt;
&amp;lt;/Component&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Astro will create the following layout:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;astro-island&lt;/code&gt; in the top level&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;astro-slot&lt;/code&gt; in the second level (since &lt;code&gt;Component&lt;/code&gt; gets content through a slot)&lt;/li&gt;
&lt;li&gt;Another &lt;code&gt;astro-island&lt;/code&gt; after &lt;code&gt;astro-slot&lt;/code&gt; since &lt;code&gt;Nested&lt;/code&gt; needs to have JavaScript functionality as well.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B4Openh2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/nested-island-and-slots.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B4Openh2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://zellwk.com/images/blog/astro-styling-frustrations/nested-island-and-slots.png" width="735" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm not sure whether this level of complexity is necessary though.&lt;/p&gt;

&lt;p&gt;Most of the time, I just one layer of &lt;code&gt;astro-island&lt;/code&gt; and a layer of &lt;code&gt;astro-slot&lt;/code&gt;. So this should be an edge case more than anything else.&lt;/p&gt;

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

&lt;p&gt;I've just shared with you when and how Astro creates &lt;code&gt;astro-island&lt;/code&gt; and &lt;code&gt;astro-slot&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I've also shared with you how to overcome the styling frustrations that happen when &lt;code&gt;astro-island&lt;/code&gt; and &lt;code&gt;astro-slot&lt;/code&gt; elements are present in the DOM.&lt;/p&gt;

&lt;p&gt;With this, you should now be able to use Astro effectively without encountering further styling issues.&lt;/p&gt;

&lt;p&gt;Hope you find this useful in your coding journey.&lt;/p&gt;

&lt;p&gt;If you wish to receive more in-depth articles about Astro, Svelte, and other web development topics, feel free to sign up for my newsletter below.&lt;/p&gt;

&lt;p&gt;That's it for today. Thanks for reading!&lt;/p&gt;

&lt;p&gt;By the way, this article is originally written on my &lt;a href="https://zellwk.com/blog/overcoming-astro-styling-frustrations/"&gt;blog&lt;/a&gt;. Feel free to visit that if you want to have these articles delivered to your email first-hand whenever they're released! 🙂.&lt;/p&gt;

</description>
      <category>astro</category>
      <category>css</category>
    </item>
  </channel>
</rss>
