<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ themes - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ themes - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 22:25:17 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/themes/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ What is Website Theming? How to Use CSS Custom Properties and Gatsby.js to Customize Your Site ]]>
                </title>
                <description>
                    <![CDATA[ In this article, I'm going to show you how to theme your website so users can customize certain elements to their tastes. We'll talk about website themes, how theming works, and we'll end with a demo so you can see it in action. Let's dive in. Table ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/website-theming-with-css-custom-properties-and-gatsbyjs/</link>
                <guid isPermaLink="false">66d4616c73634435aafcefef</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ css properties ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ themes ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Spruce Emmanuel ]]>
                </dc:creator>
                <pubDate>Thu, 01 Jul 2021 18:19:21 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/06/theming-website-preview-1-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, I'm going to show you how to theme your website so users can customize certain elements to their tastes.</p>
<p>We'll talk about website themes, how theming works, and we'll end with a demo so you can see it in action. Let's dive in.</p>
<h2 id="heading-table-of-contents">Table of Contents:</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-a-theme">What is a Website Theme?</a><br>  What is theming?</p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-should-you-care-about-website-theming">Why Should You Care About Theming?</a><br>  “It’s their screen, machine and software”<br>  Theming increases readability<br>  All the cool cats are using it - theming in the wild</p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-theme-properties">How to Use Theme Properties</a><br>  What are theme properties?<br>  What are CSS custom properties?<br>  How to set up theme properties in Gatsby.js<br>  How to store the theme properties<br>  How to transform theme properties to CSS custom properties</p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-the-theme-switcher-component">How to Use the Theme Switcher Component</a><br>  The markup<br>  How to set up the state<br>  How to update the state<br>  How to persist state to <code>LocalStorage</code></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-who-is-this-article-for">Who is this article for?</h2>
<p>This article is aimed at developers who already have a basic knowledge of CSS, React, and Gatsby who want to learn how to create a user theme-able Gatsby or React app.</p>
<p>By the end of this article, you should understand how theming works and how to implement theming on your Gatsby sites.</p>
<h2 id="heading-what-is-a-theme">What is a theme?</h2>
<p>In order to understand what website theming is, let's first look at what a <strong>website theme</strong> is and what make up a theme.</p>
<p>A theme in the context of a website is the overall look, feel, and style of your <strong>website.</strong> A theme may include:</p>
<ul>
<li><p>fonts</p>
</li>
<li><p>font size</p>
</li>
<li><p>color schemes</p>
</li>
<li><p>layouts</p>
</li>
<li><p>aesthetics</p>
</li>
</ul>
<p>A theme controls the design of your website. It determines what your website looks like from the surface, and it is the part of your website that has a direct impact on your users.</p>
<p>A theme is also a set of styles worn by a website.</p>
<h2 id="heading-what-is-theming">What is Theming?</h2>
<p>Theming is to a website what clothes are to our bodies. Imagine wearing the same clothes to a meeting, a wedding, and a farm - sounds funny right? Of course you probably wouldn't do that if you had the choice.</p>
<p>For each occasion you would wear the appropriate type or style of dress. That’s what website theming is – it allows our users to choose the look and feel of our website with a set of styles based on different occasions.</p>
<p>Theming is simply giving users the ability to make customizations to our websites and apps. You can also think about theming as a set of customizations users can make to our websites or applications based on their choices.</p>
<p>Theming happens when the user is able to tell your website what they prefer to see, for example:</p>
<ul>
<li><p>Clicking a button to change the background of a website to red or black</p>
</li>
<li><p>Increasing or decreasing the font size of a site website/application</p>
</li>
<li><p>Clicking a button to remove content not relevant to the user.</p>
</li>
</ul>
<p>Here’s a tip: letting or asking your users to determine your website theme from scratch is a bad idea. You or your team should provide users with an accessible and usable default theme, since in most cases many users will never customize “their view” on your website no matter how easy it is. |</p>
<h2 id="heading-why-should-you-care-about-website-theming">Why should you care about website theming?</h2>
<p>Apart from letting users know you care about their personal preferences, there are other reasons to let your users theme your website. Some of them include:</p>
<h3 id="heading-its-their-screen-machine-and-software">“It’s their Screen, Machine and Software”</h3>
<p>This is a quote from Jakob Nielsen's 2002 article: <a target="_blank" href="https://www.nngroup.com/articles/let-users-control-font-size/">Let users control font size</a>.</p>
<p>The fact that your website is running on the user’s screen, machine, and software (and probably draining their batteries too) is enough reason them to be able to customize their experience on your site.</p>
<h3 id="heading-theming-improves-website-readability">Theming improves website readability</h3>
<p>Quoting D. Bnonn from the article: <a target="_blank" href="https://www.smashingmagazine.com/2011/10/16-pixels-body-copy-anything-less-costly-mistake/">16 Pixels Font Size: For Body Copy. Anything Less Is A Costly Mistake</a></p>
<blockquote>
<p>Fact: Most Web Users Hate The “Normal” Font Size.</p>
</blockquote>
<p>With this fact in mind, theming can help readers out by allowing them to choose the font size that suites their eyes best.</p>
<p>Oh and here is another quote from the same article.</p>
<blockquote>
<p>Readership = Revenue.</p>
</blockquote>
<h3 id="heading-all-the-cool-cats-are-using-it-theming-in-the-wild">All the cool cats are using it – theming in the wild</h3>
<p>A lot of developers have used the idea of theming to create dark mode versions of their websites. Other’s have taken this idea further to allow users change font-size, colors, and background based on individual preferences.</p>
<p>Here's an example of this kind of customization in the Twitter web app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/twitter.com_home.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Twitter customize theme UI</em></p>
<p>Still not feeling motivated yet? If you still need more proof that theming is a good idea, <a target="_blank" href="https://darkmodelist.com/">here’s a whole list of websites, apps, and software</a> that use theming to provide dark and light modes for their users.</p>
<h2 id="heading-how-to-use-theme-properties">How to Use Theme Properties</h2>
<p>Now that you know what theming is and have seen sites that use this idea of theming in their websites and applications, let’s learn what theme properties are.</p>
<h3 id="heading-what-are-theme-properties">What are theme properties?</h3>
<p>Theme properties are a set of CSS custom properties that make up a theme. Remember that “a theme is a set of styles worn by a website” – so theme properties are all the properties that make up the styles a site wears. For example:</p>
<pre><code class="lang-css"><span class="hljs-selector-attr">[data-theme=<span class="hljs-string">"default"</span>]</span> {
  <span class="hljs-attribute">--font-size</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">--background</span>: red;
}
</code></pre>
<p>In the example above, <code>[data-theme="default"]</code> is our theme, while all the CSS custom properties inside are the theme properties. You get the idea, right?</p>
<p>Here’s a tip: your theme properties don’t have to be just CSS custom properties. They can also be any valid CSS properties that you want to apply to a specific theme.</p>
<p>Before we move forward, let’s first understand what CSS custom properties are</p>
<h3 id="heading-what-are-css-custom-properties-also-known-as-css-variables">What are CSS Custom Properties (also known as CSS variables)?</h3>
<p>CSS custom properties are entities which hold values that you can reuse throughout an entire site or document.</p>
<p>For the sake of this tutorial we are not going to cover CSS custom properties in depth. You can <a target="_blank" href="https://www.freecodecamp.org/news/css-customs-properties-cheatsheet-c86778541f7d/">read more about custom properties here</a>.</p>
<p>Also there are a lot of great tutorials out there that cover CSS custom properties and how to use them for theming, so we’ll leave the theory to those other articles.</p>
<p>For a strategic guide on how to use CSS custom properties for theming check out this awesome article: <a target="_blank" href="https://www.smashingmagazine.com/2018/05/css-custom-properties-strategy-guide/">A Strategy Guide To CSS Custom Properties</a>.</p>
<p>Although we are not covering CSS custom properties in depth, I want to point out a few reasons why CSS custom properties are ideal for website theming:</p>
<ul>
<li><p>They are reusable – you can use them throughout your CSS</p>
</li>
<li><p>They reduce the complexity of our code, since you no longer need to create different stylesheet to achieve a theme-able website</p>
</li>
<li><p>They are available at runtime, which means you can update their value in the browser, via JavaScript, with immediate results.</p>
</li>
</ul>
<h2 id="heading-how-to-set-up-theme-properties-in-gatsbyjs">How to Set Up Theme Properties in Gatsby.js</h2>
<p>Of course you can hard code theme properties directly inside your CSS file like any other CSS properties. But having to scroll up a few lines of your CSS code anytime you want to make a few changes to your themes sounds tedious, right?</p>
<p><a target="_blank" href="https://mxb.dev/about/">Max Böck</a> in his article <a target="_blank" href="https://mxb.dev/blog/color-theme-switcher/">“Color Theme Switcher”</a> advises defining our themes in a central location.</p>
<p>Having a central location (file) where you can easily access and manage your themes sounds like an interesting idea. And this is the kind of thing Gatsby was made for.</p>
<p>Quoting the Gatsby docs:</p>
<blockquote>
<p>“A core feature of Gatsby.js is it’s ability to load data from anywhere.”</p>
</blockquote>
<p>This means you can source data from a JSON file which will be available at build time. When you import this data you can then iterate over it with the <code>Array.map</code> method and render it in a React component.</p>
<h3 id="heading-how-to-store-theme-properties">How to Store Theme Properties</h3>
<p>In your Gatsby project folder, create a directory called content if it doesn't already exists. Then add a new file called <code>themes.json</code> with the following content:</p>
<pre><code class="lang-json">[
  {
    <span class="hljs-attr">"id"</span>: <span class="hljs-string">"default"</span>,
    <span class="hljs-attr">"colors"</span>: {
      <span class="hljs-attr">"primary-color"</span>: <span class="hljs-string">"#0250bb"</span>,
      <span class="hljs-attr">"text"</span>: <span class="hljs-string">"#20123a"</span>,
      <span class="hljs-attr">"text-alt"</span>: <span class="hljs-string">"#42425a"</span>,
      <span class="hljs-attr">"border"</span>: <span class="hljs-string">"#ededf0"</span>,
      <span class="hljs-attr">"background"</span>: <span class="hljs-string">"#ffffff"</span>,
      <span class="hljs-attr">"background-alt"</span>: <span class="hljs-string">"#f9f9fa"</span>,
      <span class="hljs-attr">"color-scheme"</span>: <span class="hljs-string">"light"</span>
    }
  },
  {
    <span class="hljs-attr">"id"</span>: <span class="hljs-string">"dark"</span>,
    <span class="hljs-attr">"colors"</span>: {
      <span class="hljs-attr">"primary-color"</span>: <span class="hljs-string">"#7f5af0"</span>,
      <span class="hljs-attr">"text"</span>: <span class="hljs-string">"#fffffe"</span>,
      <span class="hljs-attr">"text-alt"</span>: <span class="hljs-string">"#94a1b2"</span>,
      <span class="hljs-attr">"border"</span>: <span class="hljs-string">"#010101"</span>,
      <span class="hljs-attr">"background"</span>: <span class="hljs-string">"#16161a"</span>,
      <span class="hljs-attr">"background-alt"</span>: <span class="hljs-string">"#242629"</span>,
      <span class="hljs-attr">"color-scheme"</span>: <span class="hljs-string">"dark"</span>
    }
  },
  {
    <span class="hljs-attr">"id"</span>: <span class="hljs-string">"warm"</span>,
    <span class="hljs-attr">"colors"</span>: {
      <span class="hljs-attr">"primary-color"</span>: <span class="hljs-string">"#ff8e3c"</span>,
      <span class="hljs-attr">"text"</span>: <span class="hljs-string">"#0d0d0d"</span>,
      <span class="hljs-attr">"text-alt"</span>: <span class="hljs-string">"#2a2a2a"</span>,
      <span class="hljs-attr">"background"</span>: <span class="hljs-string">"#eff0f3"</span>,
      <span class="hljs-attr">"background-alt"</span>: <span class="hljs-string">"#fff"</span>,
      <span class="hljs-attr">"border"</span>: <span class="hljs-string">"rgba(0,0,0,.1)"</span>,
      <span class="hljs-attr">"color-scheme"</span>: <span class="hljs-string">"light"</span>
    }
  },
<span class="hljs-comment">// Add other themes here</span>
]
</code></pre>
<p>Each theme gets an <code>id</code>, a set of theme properties, and a CSS <code>color-scheme</code> property.</p>
<p>Here’s a tip – we use the CSS <code>color-scheme</code> property to tell which color scheme (light/dark) our webpage should be rendered in. For a better understanding of <code>color-scheme</code> please refer to this <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme">color scheme</a> guide.</p>
<h3 id="heading-how-to-transform-theme-properties-to-css-custom-properties">How to Transform Theme Properties to CSS Custom Properties</h3>
<p>Right now, the color themes stored in our <code>content/themes.json</code> files are just raw <strong>data</strong>. They need to be transformed into CSS custom properties before they can actually do anything meaningful.</p>
<blockquote>
<p><strong>Data</strong> is a collection of facts, such as numbers, <strong>words</strong>, measurements, observations or just descriptions of things.</p>
</blockquote>
<p>We are going to need our CSS custom properties to be dynamically generated and added as an inline <code>&lt;style&gt;</code> to the <code>&lt;head&gt;</code> of all our site pages.</p>
<p>You need to install two important plugins for this tutorial: react-helmet, a document head manager for React, and gatsby-plugin-react-helmet to allow server rendering of data that's added with React Helmet.</p>
<p>Install these plugins with this command:</p>
<pre><code class="lang-plaintext">npm installl gatsby-plugin-react-helmet react-helmet
</code></pre>
<p>To use these plugins you need to add it to the plugin array in your gatsby-config.js file located at the root of the project directory:</p>
<pre><code class="lang-plaintext">plugins: [gatsby-plugin-react-helmet]
</code></pre>
<p>Since you are going to use React helmet on all your pages, it makes sense to use it in your <code>Layout.js</code> file. In your <code>layout.js</code> file add the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> { Helmet } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-helmet"</span>
<span class="hljs-keyword">import</span> themes <span class="hljs-keyword">from</span> <span class="hljs-string">"../../content/themes.json"</span>
<span class="hljs-comment">// other imports</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Layout</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">colors</span>(<span class="hljs-params">theme</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">`
          --primary-color: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"primary-color"</span>]}</span>;
          --text: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"text"</span>]}</span>;
          --text-alt: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"text-alt"</span>]}</span>;
          --background: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"background"</span>]}</span>;
          --background-alt: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"background-alt"</span>]}</span>;
          --border: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"border"</span>]}</span>;
          --shadow: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"shadow"</span>]}</span>;
          color-scheme: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"color-scheme"</span>]}</span>;
    `</span>
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Helmet</span>&gt;</span>
        // other head meta tags

        <span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>&gt;</span>{`
    ${themes
      .map(theme =&gt; {
        if (theme.id === "default") {
          return `
          :root {
            ${colors(theme)}
          }
        `
        } else if (theme.id === "dark") {
          return `
          @media (prefers-color-scheme: dark) {
            ${colors(theme)}
          }
        `
        }
      })
      .join("")}
    ${themes
      .map(theme =&gt; {
        return `
        [data-theme="${theme.id}"] {
          ${colors(theme)}
        }
      `
      })
      .join("")}
  `}
        <span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Helmet</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"main"</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Footer</span> /&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  )
}
</code></pre>
<p>Let's break this down a bit.</p>
<p>First, the themes and react-helmet are imported from <code>content/themes.json</code> and React respectively:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> { Helmet } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-helmet"</span>
<span class="hljs-keyword">import</span> themes <span class="hljs-keyword">from</span> <span class="hljs-string">"../../content/themes.json"</span>
<span class="hljs-comment">// other imports</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Layout</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">return</span> (

  )
}
</code></pre>
<p>It creates a function which will transform our themes to CSS custom properties:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">colors</span>(<span class="hljs-params">theme</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">`
          --primary-color: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"primary-color"</span>]}</span>;
          --text: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"text"</span>]}</span>;
          --text-alt: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"text-alt"</span>]}</span>;
          --background: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"background"</span>]}</span>;
          --background-alt: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"background-alt"</span>]}</span>;
          --border: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"border"</span>]}</span>;
          --shadow: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"shadow"</span>]}</span>;
          color-scheme: <span class="hljs-subst">${theme.colors[<span class="hljs-string">"color-scheme"</span>]}</span>;
    `</span>
  }
</code></pre>
<p>Inside our <code>&lt;Helmet&gt;</code> we add a <code>&lt;style&gt;</code> tag to our document’s head.</p>
<p>Here’s a tip – if you need to add a style to the document’s head, you have to render the style as a string within curly braces.</p>
<p>In the first <code>Array.map</code> method, we check if there’s a theme with <code>id</code> equal to <code>default</code>. If there is, we set it as our default color scheme in the <code>:root{}</code>. We also check if there’s a theme with <code>id</code> equal to <code>dark</code>. If there is, we use it when the <code>prefers-color-scheme</code> of the user is dark:</p>
<pre><code class="lang-js">${themes
      .map(<span class="hljs-function"><span class="hljs-params">theme</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (theme.id === <span class="hljs-string">"default"</span>) {
          <span class="hljs-keyword">return</span> <span class="hljs-string">`
          :root {
            <span class="hljs-subst">${colors(theme)}</span>
          }
        `</span>
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (theme.id === <span class="hljs-string">"dark"</span>) {
          <span class="hljs-keyword">return</span> <span class="hljs-string">`
          @media (prefers-color-scheme: dark) {
            <span class="hljs-subst">${colors(theme)}</span>
          }
        `</span>
        }
      })
      .join(<span class="hljs-string">""</span>)}
</code></pre>
<p>In the last <code>Array.map</code> method, we iterate over our themes and each theme gets a <code>[data-theme=""]</code> attribute selector:</p>
<pre><code class="lang-js"> ${themes
      .map(<span class="hljs-function"><span class="hljs-params">theme</span> =&gt;</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">`
        [data-theme="<span class="hljs-subst">${theme.id}</span>"] {
          <span class="hljs-subst">${colors(theme)}</span>
        }
      `</span>
      })
      .join(<span class="hljs-string">""</span>)}
</code></pre>
<p>Now if you inspect the head of your site you should see all the theme properties in your <code>content/themes.json</code> file nicely generated as CSS custom properties. In fact if you add the attribute <code>data-theme="name of your theme"</code> to your <code>html</code> tag via the dev tools, your theme should work perfectly well.</p>
<h2 id="heading-how-to-use-the-theme-switcher-component">How to Use the Theme Switcher Component</h2>
<p>Well, we can't have users manually editing our site via dev tools anytime they want to use a different theme on our site. So all that’s left in this tutorial is to create a UI so that users can easily <strong>Theme</strong> our website.</p>
<h3 id="heading-the-markup">The Markup</h3>
<p>Create a new file called <code>themes.js</code> in your components directory and add the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> themes <span class="hljs-keyword">from</span> <span class="hljs-string">"../../content/theme.json"</span>

<span class="hljs-keyword">const</span> Theme = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"theme"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"theme-close text-right"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>x<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"theme-wrapper__inner"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"theme-header text-center"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">strong</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"theme-title"</span>&gt;</span>Select Theme<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
            Please Note that Changes made here will affect other pages across
            the entire site.
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"theme-content"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"schemes"</span>&gt;</span>
            {theme.map(data =&gt; {
              return (
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"scheme"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                    <span class="hljs-attr">className</span>=<span class="hljs-string">"scheme-btn js-scheme-btn"</span>
                    <span class="hljs-attr">aria-label</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">data.id</span>}`}
                    <span class="hljs-attr">name</span>=<span class="hljs-string">"scheme"</span>
                    <span class="hljs-attr">value</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">data.id</span>}`}
                    <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">backgroundColor:</span> `${<span class="hljs-attr">data.colors</span>["<span class="hljs-attr">background</span>"]}` }}
                  &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              )
            })}
          <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"theme-content"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"theme-range"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"font"</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{state.font}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xsmall"</span>&gt;</span>Aa<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                <span class="hljs-attr">type</span>=<span class="hljs-string">"range"</span>
                <span class="hljs-attr">name</span>=<span class="hljs-string">"font"</span>
                <span class="hljs-attr">min</span>=<span class="hljs-string">"10"</span>
                <span class="hljs-attr">max</span>=<span class="hljs-string">"20"</span>
                <span class="hljs-attr">step</span>=<span class="hljs-string">"2"</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">"theme-range__slider"</span>
              /&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-large"</span>&gt;</span>Aa<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Theme
</code></pre>
<p>Let’s break down this code a bit so we know what's going on.</p>
<p>First we import our themes from content/themes.js and iterate over it with a <code>Array.map</code> method. For each theme, I created a button with a background color equal to its <code>background-color</code> with a value equal to its <code>id</code>.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"schemes"</span>&gt;</span>
            {theme.map(data =&gt; {
              return (
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"scheme"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                    <span class="hljs-attr">className</span>=<span class="hljs-string">"scheme-btn js-scheme-btn"</span>
                    <span class="hljs-attr">aria-label</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">data.id</span>}`}
                    <span class="hljs-attr">name</span>=<span class="hljs-string">"scheme"</span>
                    <span class="hljs-attr">value</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">data.id</span>}`}
                    <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">backgroundColor:</span> `${<span class="hljs-attr">data.colors</span>["<span class="hljs-attr">background</span>"]}` }}
                  &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              )
            })}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</code></pre>
<p>To change the font size of our text, I also added an <code>input</code> field of type <code>range</code> with a <code>min</code> value of <code>10px</code> and <code>max</code> value of <code>20px</code>.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
  <span class="hljs-attr">type</span>=<span class="hljs-string">"range"</span>
  <span class="hljs-attr">name</span>=<span class="hljs-string">"font"</span>
  <span class="hljs-attr">min</span>=<span class="hljs-string">"10"</span>
  <span class="hljs-attr">max</span>=<span class="hljs-string">"20"</span>
  <span class="hljs-attr">step</span>=<span class="hljs-string">"2"</span>
  <span class="hljs-attr">className</span>=<span class="hljs-string">"theme-range__slider"</span>
  /&gt;</span>
</code></pre>
<p>With some added CSS (which we won't cover in this tutorial) we now have a UI that looks like the one below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/localhost_8000_--13-.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>iamspruce.dev customize theme UI</em></p>
<h3 id="heading-how-to-set-up-the-state">How to Set Up the State</h3>
<p>We'll start by importing the <code>useState()</code> hook from React:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React, { useState} <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">const</span> Theme = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-keyword">return</span> (
  )
}
</code></pre>
<p>We use React <a target="_blank" href="https://reactjs.org/docs/hooks-reference.html#lazy-initial-state">Lazy Initialization</a>, which lets us pass a function to <code>useState()</code> that we'll use during the initial render.</p>
<p>Quoting the React docs:</p>
<blockquote>
<p>"If the initial state is the result of an expensive calculation, you may provide a function instead, which will be executed only in the initial render."</p>
</blockquote>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React, { useState} <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> themes <span class="hljs-keyword">from</span> <span class="hljs-string">"../../content/theme.json"</span>

<span class="hljs-keyword">const</span> Theme = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> [state, setState] = useState(<span class="hljs-function">() =&gt;</span> {
     <span class="hljs-keyword">const</span> localVal =
       <span class="hljs-keyword">typeof</span> <span class="hljs-built_in">window</span> !== <span class="hljs-string">"undefined"</span> &amp;&amp; <span class="hljs-built_in">window</span>.localStorage.getItem(<span class="hljs-string">"theme"</span>)
     <span class="hljs-keyword">let</span> obj = {
       <span class="hljs-attr">font</span>: <span class="hljs-number">15</span>,
       <span class="hljs-attr">scheme</span>: <span class="hljs-string">"default"</span>,
     }
     <span class="hljs-keyword">return</span> localVal !== <span class="hljs-literal">null</span> ? <span class="hljs-built_in">JSON</span>.parse(localVal) : obj
   })
  <span class="hljs-keyword">return</span> (

  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Theme
</code></pre>
<p>In our case, we’re using it to check for the value in <code>localStorage()</code>. If the value exists, will use that as our initial value. Otherwise, will use the default <code>obj</code>.</p>
<p>We’re checking if the window object exists <code>(typeof window !== “undefined”)</code> because at build time the window’s object does not exist. If you run <code>gatsby build</code> without checking if the windows object exists or not, you’ll get an error that looks like this:</p>
<p><code>WebpackError: ReferenceError: localStorage is not defined</code></p>
<h3 id="heading-how-to-update-the-state">How to Update the State</h3>
<p>The next step is to have an <code>onClick</code> and <code>onChange</code> eventListener update our state. For that we are going to create a function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React, { useState} <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> themes <span class="hljs-keyword">from</span> <span class="hljs-string">"../../content/theme.json"</span>

<span class="hljs-keyword">const</span> Theme = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> [state, setState] = useState(<span class="hljs-function">() =&gt;</span> {
     <span class="hljs-keyword">const</span> localVal =
       <span class="hljs-keyword">typeof</span> <span class="hljs-built_in">window</span> !== <span class="hljs-string">"undefined"</span> &amp;&amp; <span class="hljs-built_in">window</span>.localStorage.getItem(<span class="hljs-string">"theme"</span>)
     <span class="hljs-keyword">let</span> obj = {
       <span class="hljs-attr">font</span>: <span class="hljs-number">15</span>,
       <span class="hljs-attr">scheme</span>: <span class="hljs-string">"default"</span>,
     }
     <span class="hljs-keyword">return</span> localVal !== <span class="hljs-literal">null</span> ? <span class="hljs-built_in">JSON</span>.parse(localVal) : obj
   })
<span class="hljs-comment">// the update function</span>
  <span class="hljs-keyword">const</span> update = <span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> { name, value } = e.target
    setState(<span class="hljs-function"><span class="hljs-params">prevState</span> =&gt;</span> ({
      ...prevState,
      [name]: value,
    }))
  }

  <span class="hljs-keyword">return</span> (

  )
}
</code></pre>
<p>We passed in a Object as an initial value for our <code>useState</code> because we can update multiple states with one <code>useState</code> hook. We now need to set the update function on our UI:</p>
<pre><code class="lang-js">...
{theme.map(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"scheme"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
       <span class="hljs-attr">onClick</span>=<span class="hljs-string">{update}</span> // <span class="hljs-attr">set</span> <span class="hljs-attr">the</span> <span class="hljs-attr">update</span> <span class="hljs-attr">function</span> <span class="hljs-attr">to</span> <span class="hljs-attr">an</span> <span class="hljs-attr">Onclick</span> <span class="hljs-attr">event</span> 
       <span class="hljs-attr">className</span>=<span class="hljs-string">"scheme-btn js-scheme-btn"</span>
       <span class="hljs-attr">aria-label</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">data.id</span>}`}
       <span class="hljs-attr">name</span>=<span class="hljs-string">"scheme"</span>
       <span class="hljs-attr">value</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">data.id</span>}`}
       <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">backgroundColor:</span> `${<span class="hljs-attr">data.colors</span>["<span class="hljs-attr">background</span>"]}` }}
       &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
   )
})}

&lt;input
  type=<span class="hljs-string">"range"</span>
  name=<span class="hljs-string">"font"</span>
  min=<span class="hljs-string">"10"</span>
  max=<span class="hljs-string">"20"</span>
  step=<span class="hljs-string">"2"</span>
  className=<span class="hljs-string">"theme-range__slider"</span>
  onChange={update} <span class="hljs-comment">// set the update function to an Onchange event</span>
  value={state.font}
/&gt;
</code></pre>
<h3 id="heading-how-to-persist-our-changes-in-localstorage">How to Persist Our Changes In LocalStorage</h3>
<p>The final step is to make sure we update <code>localStorage</code> and our website with the current values from our state whenever the state value changes. For that we’ll use the <code>useEffect</code> Hook, which lets us <strong>run some code after React has updated the DOM.</strong></p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React, { useState} <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> themes <span class="hljs-keyword">from</span> <span class="hljs-string">"../../content/theme.json"</span>

<span class="hljs-keyword">const</span> Theme = <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-keyword">const</span> [state, setState] = useState(<span class="hljs-function">() =&gt;</span> {
     <span class="hljs-keyword">const</span> localVal =
       <span class="hljs-keyword">typeof</span> <span class="hljs-built_in">window</span> !== <span class="hljs-string">"undefined"</span> &amp;&amp; <span class="hljs-built_in">window</span>.localStorage.getItem(<span class="hljs-string">"theme"</span>)
     <span class="hljs-keyword">let</span> obj = {
       <span class="hljs-attr">font</span>: <span class="hljs-number">15</span>,
       <span class="hljs-attr">scheme</span>: <span class="hljs-string">"default"</span>,
     }
     <span class="hljs-keyword">return</span> localVal !== <span class="hljs-literal">null</span> ? <span class="hljs-built_in">JSON</span>.parse(localVal) : obj
   })

  <span class="hljs-keyword">const</span> update = <span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> { name, value } = e.target
    setState(<span class="hljs-function"><span class="hljs-params">prevState</span> =&gt;</span> ({
      ...prevState,
      [name]: value,
    }))
  }

<span class="hljs-comment">// persisting state to localStorage</span>
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">window</span>.localStorage.setItem(<span class="hljs-string">"theme"</span>, <span class="hljs-built_in">JSON</span>.stringify(state))
    <span class="hljs-keyword">let</span> root = <span class="hljs-built_in">document</span>.documentElement
    root.setAttribute(<span class="hljs-string">"data-theme"</span>, state.scheme)
    root.style.setProperty(<span class="hljs-string">"--font-size"</span>, <span class="hljs-string">`<span class="hljs-subst">${state.font}</span>px`</span>)
  }, [state])

  <span class="hljs-keyword">return</span> (

  )
}
</code></pre>
<p>Congratulations! If you made it this far you now have a complete user theme-able website. The overall design of our <strong>switch theme UI</strong> now looks like this:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/cMboQU-qwyE" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>For a live preview of the site, visit <a target="_blank" href="https://www.iamspruce.dev/">https://www.iamspruce.dev/</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>There's really no limit with what you can do with <strong>theming</strong>. Although this tutorial uses Gatsby.js, you can easily apply these concepts to other React-based static site generators.</p>
<p>If you found this tutorial useful, kindly follow me on Twitter <a target="_blank" href="https://twitter.com/sprucekhalifa">@sprucekhalifa</a> .</p>
<p>Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Hugo vs Jekyll: an Epic Battle of Static Site Generator Themes ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we'll compare the nuances of creating themes for the top two static site generators. I recently took on the task of creating a documentation site theme for two projects. Both projects needed the same basic features, but one uses Jeky... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/hugo-vs-jekyll-battle-of-static-site-generator-themes/</link>
                <guid isPermaLink="false">66bd8f5f27629f4c5e1893b2</guid>
                
                    <category>
                        <![CDATA[ Hugo ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ jekyll ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Static Site Generators ]]>
                    </category>
                
                    <category>
                        <![CDATA[ themes ]]>
                    </category>
                
                    <category>
                        <![CDATA[ website development, ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Victoria Drake ]]>
                </dc:creator>
                <pubDate>Mon, 27 Apr 2020 13:42:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/cover-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we'll compare the nuances of creating themes for the top two static site generators.</p>
<p>I recently took on the task of creating a documentation site theme for two projects. Both projects needed the same basic features, but one uses Jekyll while the other uses Hugo.</p>
<p>In typical developer rationality, there was clearly only one option. I decided to create the same theme in both frameworks, and to give you, dear reader, a side-by-side comparison.</p>
<p>This post isn’t a comprehensive theme-building guide, but is rather intended to familiarize you with the process of building a theme in either generator. Here's what we'll cover:</p>
<ul>
<li>How theme files are organized</li>
<li>Where to put content</li>
<li>How templating works</li>
<li>Creating a top-level menu with the <code>pages</code> object</li>
<li>Creating a menu with nested links from a data list</li>
<li>Putting the template together</li>
<li>Creating styles</li>
<li>How to configure and deploy to GitHub Pages</li>
</ul>
<p>Here’s a crappy wireframe of the theme I’m going to create.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/wireframe.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you’re planning to build-along, it may be helpful to serve the theme locally as you build it – and both generators offer this functionality. For Jekyll, run <code>jekyll serve</code>, and for Hugo, <code>hugo serve</code>.</p>
<p>There are two main elements: the main content area, and the all-important sidebar menu. To create them, you’ll need template files that tell the site generator how to generate the HTML page. To organize theme template files in a sensible way, you first need to know what  directory structure the site generator expects.</p>
<h2 id="heading-how-theme-files-are-organized">How theme files are organized</h2>
<p>Jekyll supports gem-based themes, which users can install like any other Ruby gems. This method hides theme files in the gem, so for the purposes of this comparison, we aren’t using gem-based themes.</p>
<p>When you run <code>jekyll new-theme &lt;name&gt;</code>, Jekyll will scaffold a new theme for you. Here’s what those files look like:</p>
<pre><code class="lang-sh">.
├── assets
├── Gemfile
├── _includes
├── _layouts
│   ├── default.html
│   ├── page.html
│   └── post.html
├── LICENSE.txt
├── README.md
├── _sass
└── &lt;name&gt;.gemspec
</code></pre>
<p>The directory names are appropriately descriptive. The <code>_includes</code> directory is for small bits of code that you reuse in different places,  in much the same way you’d put butter on everything. (Just me?) </p>
<p>The <code>_layouts</code> directory contains templates for different types of pages on your site. The <code>_sass</code> folder is for <a target="_blank" href="https://sass-lang.com/documentation/syntax">Sass</a> files used to build your site’s stylesheet.</p>
<p>You can scaffold a new Hugo theme by running <code>hugo new theme &lt;name&gt;</code>. It has these files:</p>
<pre><code class="lang-sh">.
├── archetypes
│   └── default.md
├── layouts
│   ├── 404.html
│   ├── _default
│   │   ├── baseof.html
│   │   ├── list.html
│   │   └── single.html
│   ├── index.html
│   └── partials
│       ├── footer.html
│       ├── header.html
│       └── head.html
├── LICENSE
├── static
│   ├── css
│   └── js
└── theme.toml
</code></pre>
<p>You can see some similarities. Hugo’s page template files are tucked into <code>layouts/</code>. Note that the <code>_default</code> page type has files for a <code>list.html</code> and a <code>single.html</code>. </p>
<p>Unlike Jekyll, Hugo uses these specific file names to distinguish between <a target="_blank" href="https://gohugo.io/templates/lists/">list pages</a> (like a page with links to all your blog posts on it) and <a target="_blank" href="https://gohugo.io/templates/single-page-templates/">single pages</a> (like one of your blog posts). The <code>layouts/partials/</code> directory contains the buttery reusable bits, and stylesheet files have a spot picked out in <code>static/css/</code>.</p>
<p>These directory structures aren’t set in stone, as both site generators allow some measure of customization. For example, Jekyll lets  you define <a target="_blank" href="https://jekyllrb.com/docs/collections/">collections</a>, and Hugo makes use of <a target="_blank" href="https://gohugo.io/content-management/page-bundles/">page bundles</a>. These features let you organize your content multiple ways, but for now, let's look at where to put some simple pages.</p>
<h2 id="heading-where-to-put-content">Where to put content</h2>
<p>To create a site menu that looks like this:</p>
<pre><code class="lang-md">Introduction
<span class="hljs-code">    Getting Started
    Configuration
    Deploying
Advanced Usage
    All Configuration Settings
    Customizing
    Help and Support</span>
</code></pre>
<p>You’ll need two sections (“Introduction” and “Advanced Usage”) containing their respective subsections.</p>
<p>Jekyll isn’t strict with its content location. It expects pages in the root of your site, and will build whatever’s there. Here’s how you might organize these pages in your Jekyll site root:</p>
<pre><code class="lang-sh">.
├── 404.html
├── assets
├── Gemfile
├── _includes
├── index.markdown
├── intro
│   ├── config.md
│   ├── deploy.md
│   ├── index.md
│   └── quickstart.md
├── _layouts
│   ├── default.html
│   ├── page.html
│   └── post.html
├── LICENSE.txt
├── README.md
├── _sass
├── &lt;name&gt;.gemspec
└── usage
    ├── customizing.md
    ├── index.md
    ├── settings.md
    └── support.md
</code></pre>
<p>You can change the location of the site source in your <a target="_blank" href="https://jekyllrb.com/docs/configuration/default/">Jekyll configuration</a>.</p>
<p>In Hugo, all rendered content is expected in the <code>content/</code> folder. This prevents Hugo from trying to render pages you don’t want, such as <code>404.html</code>, as site content. Here’s how you might organize your <code>content/</code> directory in Hugo:</p>
<pre><code class="lang-sh">.
├── _index.md
├── intro
│   ├── config.md
│   ├── deploy.md
│   ├── _index.md
│   └── quickstart.md
└── usage
    ├── customizing.md
    ├── _index.md
    ├── settings.md
    └── support.md
</code></pre>
<p>To Hugo, <code>_index.md</code> and <code>index.md</code> mean different things. It can be helpful to know what kind of <a target="_blank" href="https://gohugo.io/content-management/page-bundles/">Page Bundle</a> you want for each section: Leaf, which has no children, or Branch.</p>
<p>Now that you have some idea of where to put things, let’s look at how to build a page template.</p>
<h2 id="heading-how-templating-works">How templating works</h2>
<p>Jekyll page templates are built with the <a target="_blank" href="https://jekyllrb.com/docs/liquid/">Liquid templating language</a>. It uses braces to output variable content to a page, such as the page’s title: <code>{{ page.title }}</code>.</p>
<p>Hugo’s templates also use braces, but they’re built with <a target="_blank" href="https://gohugo.io/templates/introduction/">Go Templates</a>. The syntax is similar, but different: <code>{{ .Title }}</code>.</p>
<p>Both Liquid and Go Templates can handle logic. Liquid uses <em>tags</em> syntax to denote logic operations:</p>
<pre><code class="lang-liquid">{% if user %}
  Hello {{ user.name }}!
{% endif %}
</code></pre>
<p>And Go Templates places its functions and arguments in its braces syntax:</p>
<pre><code class="lang-go">{{ <span class="hljs-keyword">if</span> .User }}
    Hello {{ .User }}!
{{ end }}
</code></pre>
<p>Templating languages allow you to build one  skeleton HTML page, then tell the site generator to put variable content in areas you define. Let’s compare two possible <code>default</code> page templates for Jekyll and Hugo.</p>
<p>Jekyll’s scaffold <code>default</code> theme is bare, so we’ll look at their starter theme <a target="_blank" href="https://github.com/jekyll/minima">Minima</a>. Here’s <code>_layouts/default.html</code> in Jekyll (Liquid):</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"{{ page.lang | default: site.lang | default: "</span><span class="hljs-attr">en</span>" }}"&gt;</span>

  {%- include head.html -%}

  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

    {%- include header.html -%}

    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-content"</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Content"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"wrapper"</span>&gt;</span>
        {{ content }}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>

    {%- include footer.html -%}

  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Here’s Hugo’s scaffold theme <code>layouts/_default/baseof.html</code> (Go Templates):</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
    {{- partial "head.html" . -}}
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
        {{- partial "header.html" . -}}
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"content"</span>&gt;</span>
        {{- block "main" . }}{{- end }}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        {{- partial "footer.html" . -}}
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Different syntax, same idea. Both templates pull in reusable bits for <code>head.html</code>, <code>header.html</code>, and <code>footer.html</code>.  These show up on a lot of pages, so it makes sense not to have to  repeat yourself. </p>
<p>Both templates also have a spot for the main content, though the Jekyll template uses a variable (<code>{{ content }}</code>) while Hugo uses a block (<code>{{- block "main" . }}{{- end }}</code>). <a target="_blank" href="https://gohugo.io/templates/base/#readout">Blocks</a> are just another way Hugo lets you define reusable bits.</p>
<p>Now that you know how templating works, you can build the sidebar menu for the theme.</p>
<h2 id="heading-creating-a-top-level-menu-with-the-pages-object">Creating a top-level menu with the <code>pages</code> object</h2>
<p>You can programmatically create a top-level menu from your pages. It will look like this:</p>
<pre><code class="lang-md">Introduction
Advanced Usage
</code></pre>
<p>Let’s start with Jekyll. You can display links to site pages in your Liquid template by iterating through the <code>site.pages</code> object that Jekyll provides and building a list:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    {% for page in site.pages %}
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ page.url | absolute_url }}"</span>&gt;</span>{{ page.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    {% endfor %}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</code></pre>
<p>This returns all of the site’s pages, including all the ones that you might not want, like <code>404.html</code>. You can filter for the pages you actually want with a couple more tags, such as conditionally including pages if they have a <code>section: true</code> parameter set:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    {% for page in site.pages %}
    {%- if page.section -%}
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ page.url | absolute_url }}"</span>&gt;</span>{{ page.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    {%- endif -%}
    {% endfor %}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</code></pre>
<p>You can achieve the same effect with slightly less code in Hugo. Loop through Hugo’s <code>.Pages</code> object using Go Template’s <a target="_blank" href="https://golang.org/pkg/text/template/#hdr-Actions"><code>range</code> action</a>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
{{ range .Pages }}
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{.Permalink}}"</span>&gt;</span>{{.Title}}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
{{ end }}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</code></pre>
<p>This template uses the <code>.Pages</code> object to return all the top-level pages in <code>content/</code> of your Hugo site. Since Hugo uses a specific folder for the site content you want rendered, there’s no additional filtering necessary to build a simple menu of site pages.</p>
<h2 id="heading-creating-a-menu-with-nested-links-from-a-data-list">Creating a menu with nested links from a data list</h2>
<p>Both site generators can use a separately defined data list of links to render a menu in your template. This is more suitable for creating nested links, like this:</p>
<pre><code class="lang-md">Introduction
<span class="hljs-code">    Getting Started
    Configuration
    Deploying
Advanced Usage
    All Configuration Settings
    Customizing
    Help and Support</span>
</code></pre>
<p>Jekyll supports <a target="_blank" href="https://jekyllrb.com/docs/datafiles/">data files</a> in a few formats, including YAML. Here’s the definition for the menu above in <code>_data/menu.yml</code>:</p>
<pre><code class="lang-yml"><span class="hljs-attr">section:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Introduction</span>
    <span class="hljs-attr">url:</span> <span class="hljs-string">/intro</span>
    <span class="hljs-attr">subsection:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Getting</span> <span class="hljs-string">Started</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/quickstart</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Configuration</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/config</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Deploying</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/deploy</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Advanced</span> <span class="hljs-string">Usage</span>
    <span class="hljs-attr">url:</span> <span class="hljs-string">/usage</span>
    <span class="hljs-attr">subsection:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Customizing</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/customizing</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">All</span> <span class="hljs-string">Configuration</span> <span class="hljs-string">Settings</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/settings</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Help</span> <span class="hljs-string">and</span> <span class="hljs-string">Support</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/support</span>
</code></pre>
<p>Here’s how to render the data in the sidebar template:</p>
<pre><code class="lang-html">{% for a in site.data.menu.section %}
<span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ a.url }}"</span>&gt;</span>{{ a.page }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    {% for b in a.subsection %}
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ b.url }}"</span>&gt;</span>{{ b.page }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    {% endfor %}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
{% endfor %}
</code></pre>
<p>This method allows you to build a custom menu, two nesting levels deep. The nesting levels are limited by the <code>for</code> loops in the template. For a recursive version that handles further levels of nesting, see <a target="_blank" href="https://jekyllrb.com/tutorials/navigation/#scenario-9-nested-tree-navigation-with-recursion">Nested tree navigation with recursion</a>.</p>
<p>Hugo does something similar with its <a target="_blank" href="https://gohugo.io/templates/menu-templates/#section-menu-for-lazy-bloggers">menu templates</a>. You can define menu links in your <a target="_blank" href="https://gohugo.io/getting-started/configuration/">Hugo site config</a>, and even add useful properties that Hugo understands, like weighting. Here’s a definition of the menu above in <code>config.yaml</code>:</p>
<pre><code class="lang-yml"><span class="hljs-attr">sectionPagesMenu:</span> <span class="hljs-string">main</span>

<span class="hljs-attr">menu:</span>  
  <span class="hljs-attr">main:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">identifier:</span> <span class="hljs-string">intro</span>
      <span class="hljs-attr">name:</span> <span class="hljs-string">Introduction</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">1</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Getting</span> <span class="hljs-string">Started</span>
      <span class="hljs-attr">parent:</span> <span class="hljs-string">intro</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/quickstart/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">1</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Configuration</span>
      <span class="hljs-attr">parent:</span> <span class="hljs-string">intro</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/config/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">2</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploying</span>
      <span class="hljs-attr">parent:</span> <span class="hljs-string">intro</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/deploy/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">3</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">identifier:</span> <span class="hljs-string">usage</span>
      <span class="hljs-attr">name:</span> <span class="hljs-string">Advanced</span> <span class="hljs-string">Usage</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Customizing</span>
      <span class="hljs-attr">parent:</span> <span class="hljs-string">usage</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/customizing/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">2</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">All</span> <span class="hljs-string">Configuration</span> <span class="hljs-string">Settings</span>
      <span class="hljs-attr">parent:</span> <span class="hljs-string">usage</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/settings/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">1</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Help</span> <span class="hljs-string">and</span> <span class="hljs-string">Support</span>
      <span class="hljs-attr">parent:</span> <span class="hljs-string">usage</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/support/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">3</span>
</code></pre>
<p>Hugo uses the <code>identifier</code>, which must match the section name, along with the <code>parent</code> variable to handle nesting. Here’s how to render the menu in the sidebar template:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    {{ range .Site.Menus.main }}
    {{ if .HasChildren }}
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ .URL }}"</span>&gt;</span>{{ .Name }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"sub-menu"</span>&gt;</span>
        {{ range .Children }}
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ .URL }}"</span>&gt;</span>{{ .Name }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        {{ end }}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    {{ else }}
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ .URL }}"</span>&gt;</span>{{ .Name }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    {{ end }}
    {{ end }}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</code></pre>
<p>The <code>range</code> function iterates over the menu data, and Hugo’s <code>.Children</code> variable handles nested pages for you.</p>
<h2 id="heading-putting-the-template-together">Putting the template together</h2>
<p>With your menu in your reusable sidebar bit (<code>_includes/sidebar.html</code> for Jekyll and <code>partials/sidebar.html</code> for Hugo), you can add it to the <code>default.html</code> template.</p>
<p>In Jekyll:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"{{ page.lang | default: site.lang | default: "</span><span class="hljs-attr">en</span>" }}"&gt;</span>

{%- include head.html -%}

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    {%- include sidebar.html -%}

    {%- include header.html -%}

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"content"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-content"</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Content"</span>&gt;</span>
        {{ content }}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    {%- include footer.html -%}

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>In Hugo:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
{{- partial "head.html" . -}}

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    {{- partial "sidebar.html" . -}}

    {{- partial "header.html" . -}}
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"content"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-content"</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Content"</span>&gt;</span>
        {{- block "main" . }}{{- end }}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    {{- partial "footer.html" . -}}
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>When the site is generated, each page will contain all the code from your <code>sidebar.html</code>.</p>
<h2 id="heading-create-a-stylesheet">Create a stylesheet</h2>
<p>Both site generators accept Sass for creating CSS stylesheets. Jekyll <a target="_blank" href="https://jekyllrb.com/docs/assets/">has Sass processing built in</a>, and Hugo uses <a target="_blank" href="https://gohugo.io/hugo-pipes/scss-sass/">Hugo Pipes</a>. Both options have some quirks.</p>
<h3 id="heading-sass-and-css-in-jekyll">Sass and CSS in Jekyll</h3>
<p>To process a Sass file in Jekyll, create your style definitions in the <code>_sass</code> directory. For example, in a file at <code>_sass/style-definitions.scss</code>:</p>
<pre><code class="lang-scss"><span class="hljs-variable">$background-color</span>: <span class="hljs-number">#eef</span> !default;
<span class="hljs-variable">$text-color</span>: <span class="hljs-number">#111</span> !default;

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$background-color</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-variable">$text-color</span>;
}
</code></pre>
<p>Jekyll won’t generate this file directly, as it only processes files with front matter. To create the end-result  filepath for your site’s stylesheet, use a placeholder with empty front matter where you want the <code>.css</code> file to appear. For example, <code>assets/css/style.scss</code>. In this file, simply import your styles:</p>
<pre><code class="lang-scss">---
---

<span class="hljs-keyword">@import</span> <span class="hljs-string">"style-definitions"</span>;
</code></pre>
<p>This rather hackish configuration has an upside: you can use Liquid template tags and variables in your placeholder file. This is a nice way to allow users to set variables from the site <code>_config.yml</code>, for example.</p>
<p>The resulting CSS stylesheet in your generated site has the path <code>/assets/css/style.css</code>. You can link to it in your site’s <code>head.html</code> using:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ "</span>/<span class="hljs-attr">assets</span>/<span class="hljs-attr">css</span>/<span class="hljs-attr">style.css</span>" | <span class="hljs-attr">relative_url</span> }}" <span class="hljs-attr">media</span>=<span class="hljs-string">"screen"</span>&gt;</span>
</code></pre>
<h3 id="heading-sass-and-hugo-pipes-in-hugo">Sass and Hugo Pipes in Hugo</h3>
<p>Hugo uses <a target="_blank" href="https://gohugo.io/hugo-pipes/scss-sass/">Hugo Pipes</a> to process Sass to CSS. You can achieve this by using Hugo’s asset processing function, <code>resources.ToCSS</code>, which expects a source in the <code>assets/</code> directory. It takes the SCSS file as an argument. </p>
<p>With your style definitions in a Sass file at <code>assets/sass/style.scss</code>, here’s how to get, process, and link your Sass in your theme’s <code>head.html</code>:</p>
<pre><code class="lang-html">{{ $style := resources.Get "/sass/style.scss" | resources.ToCSS }}
<span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ $style.RelPermalink }}"</span> <span class="hljs-attr">media</span>=<span class="hljs-string">"screen"</span>&gt;</span>
</code></pre>
<p>Hugo asset processing <a target="_blank" href="https://gohugo.io/troubleshooting/faq/#i-get-tocss--this-feature-is-not-available-in-your-current-hugo-version">requires extended Hugo</a>, which you may not have by default. You can get extended Hugo from the <a target="_blank" href="https://github.com/gohugoio/hugo/releases">releases page</a>.</p>
<h2 id="heading-configure-and-deploy-to-github-pages">Configure and deploy to GitHub Pages</h2>
<p>Before your site generator can build your site, it needs a  configuration file to set some necessary parameters. Configuration files  live in the site root directory. Among other settings, you can declare  the name of the theme to use when building the site.</p>
<h3 id="heading-configure-jekyll">Configure Jekyll</h3>
<p>Here’s a minimal <code>_config.yml</code> for Jekyll:</p>
<pre><code class="lang-yml"><span class="hljs-attr">title:</span> <span class="hljs-string">Your</span> <span class="hljs-string">awesome</span> <span class="hljs-string">title</span>
<span class="hljs-attr">description:</span> <span class="hljs-string">&gt;-</span> <span class="hljs-comment"># this means to ignore newlines until "baseurl:"</span>
  <span class="hljs-string">Write</span> <span class="hljs-string">an</span> <span class="hljs-string">awesome</span> <span class="hljs-string">description</span> <span class="hljs-string">for</span> <span class="hljs-string">your</span> <span class="hljs-string">new</span> <span class="hljs-string">site</span> <span class="hljs-string">here.</span> <span class="hljs-string">You</span> <span class="hljs-string">can</span> <span class="hljs-string">edit</span> <span class="hljs-string">this</span>
  <span class="hljs-string">line</span> <span class="hljs-string">in</span> <span class="hljs-string">_config.yml.</span> <span class="hljs-string">It</span> <span class="hljs-string">will</span> <span class="hljs-string">appear</span> <span class="hljs-string">in</span> <span class="hljs-string">your</span> <span class="hljs-string">document</span> <span class="hljs-string">head</span> <span class="hljs-string">meta</span> <span class="hljs-string">(for</span>
  <span class="hljs-string">Google</span> <span class="hljs-string">search</span> <span class="hljs-string">results)</span> <span class="hljs-string">and</span> <span class="hljs-string">in</span> <span class="hljs-string">your</span> <span class="hljs-string">feed.xml</span> <span class="hljs-string">site</span> <span class="hljs-string">description.</span>
<span class="hljs-attr">baseurl:</span> <span class="hljs-string">""</span> <span class="hljs-comment"># the subpath of your site, e.g. /blog</span>
<span class="hljs-attr">url:</span> <span class="hljs-string">""</span> <span class="hljs-comment"># the base hostname &amp; protocol for your site, e.g. http://example.com</span>
<span class="hljs-attr">theme:</span> <span class="hljs-comment"># for gem-based themes</span>
<span class="hljs-attr">remote_theme:</span> <span class="hljs-comment"># for themes hosted on GitHub, when used with GitHub Pages</span>
</code></pre>
<p>With <code>remote_theme</code>, any <a target="_blank" href="https://help.github.com/en/github/working-with-github-pages/adding-a-theme-to-your-github-pages-site-using-jekyll#adding-a-jekyll-theme-in-your-sites-_configyml-file">Jekyll theme hosted on GitHub can be used</a> with sites hosted on GitHub Pages.</p>
<p>Jekyll has a <a target="_blank" href="https://jekyllrb.com/docs/configuration/default/">default configuration</a>, so any parameters added to your configuration file will override the defaults. Here are <a target="_blank" href="https://jekyllrb.com/docs/configuration/options/">additional configuration settings</a>.</p>
<h3 id="heading-configure-hugo">Configure Hugo</h3>
<p>Here’s a minimal example of Hugo’s <code>config.yml</code>:</p>
<pre><code class="lang-yml"><span class="hljs-attr">baseURL:</span> <span class="hljs-string">https://example.com/</span> <span class="hljs-comment"># The full domain your site will live at</span>
<span class="hljs-attr">languageCode:</span> <span class="hljs-string">en-us</span>
<span class="hljs-attr">title:</span> <span class="hljs-string">Hugo</span> <span class="hljs-string">Docs</span> <span class="hljs-string">Site</span>
<span class="hljs-attr">theme:</span> <span class="hljs-comment"># theme name</span>
</code></pre>
<p>Hugo makes no assumptions, so if a necessary parameter is missing, you’ll see a warning when building or serving your site. Here are <a target="_blank" href="https://gohugo.io/getting-started/configuration/#all-configuration-settings">all configuration settings for Hugo</a>.</p>
<h3 id="heading-deploy-to-github-pages">Deploy to GitHub Pages</h3>
<p>Both generators build your site with a command.</p>
<p>For Jekyll, use <code>jekyll build</code>. See <a target="_blank" href="https://jekyllrb.com/docs/configuration/options/#build-command-options">further build options here</a>.</p>
<p>For Hugo, use <code>hugo</code>. You can run <code>hugo help</code> or see <a target="_blank" href="https://gohugo.io/getting-started/usage/#test-installation">further build options here</a>.</p>
<p>You’ll have to choose the source for your GitHub Pages site. Once done, your site will update each time you push a new build. Of course, you can also automate your GitHub Pages build using GitHub Actions. Here’s one for <a target="_blank" href="https://github.com/victoriadrake/hugo-latest-cd">building and deploying with Hugo</a>, and one for <a target="_blank" href="https://github.com/victoriadrake/jekyll-cd">building and deploying Jekyll</a>.</p>
<h2 id="heading-showtime">Showtime!</h2>
<p>All the substantial differences between these two generators are under the hood. All the same, let’s take a look at the finished themes, in two color variations.</p>
<p>Here’s Hugo:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/ogd_hugo.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here's Jekyll:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/ogd_jekyll.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-wait-who-won">Wait who won?</h2>
<p>?</p>
<p>Both Hugo and Jekyll have their quirks and conveniences.</p>
<p>From this developer’s perspective, Jekyll is a workable choice for simple sites without complicated organizational needs. If you’re looking to render some one-page posts in an <a target="_blank" href="https://jekyllrb.com/docs/themes/">available theme</a> and host with GitHub Pages, Jekyll will get you up and running fairly quickly.</p>
<p>Personally, I use Hugo. I like the organizational capabilities of its Page Bundles, and it’s backed by a dedicated and conscientious team that really seems to strive to facilitate convenience for their users. This is evident in Hugo’s many functions, and handy tricks like <a target="_blank" href="https://gohugo.io/content-management/image-processing/">Image Processing</a> and <a target="_blank" href="https://gohugo.io/content-management/shortcodes/">Shortcodes</a>. They seem to release new fixes and versions about as often as I make a new cup of coffee - which, depending on your use case, may be fantastic, or annoying.</p>
<p>If you still can’t decide, don’t worry. The <a target="_blank" href="https://github.com/opengitdocs">OpenGitDocs documentation theme</a> I created is available for both Hugo and Jekyll. Start with one, switch later if you want. That’s the benefit of having options.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Themes Engine Using CSS Variables and React Context ]]>
                </title>
                <description>
                    <![CDATA[ By Dor Shinar CSS variables are really cool. You can use them for a lot of things, like applying themes in your application with ease.  In this tutorial I'll show you how to integrate them with React to create a ThemeComponent (with context!). CSS Va... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/themes-using-css-variables-and-react-context/</link>
                <guid isPermaLink="false">66d45e40bc9760a197a10382</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ themes ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 29 Jan 2020 07:23:32 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/01/cover-3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Dor Shinar</p>
<p>CSS variables are really cool. You can use them for a lot of things, like applying themes in your application with ease. </p>
<p>In this tutorial I'll show you how to integrate them with React to create a <code>ThemeComponent</code> (with context!).</p>
<h2 id="heading-css-variables-in-a-gist">CSS Variables in a Gist</h2>
<p>So first of all, I'd like to explain briefly what CSS variables (or in their formal name - CSS custom properties) are, and how to use them.</p>
<p>CSS variables are a way for us to define variables that will be applied throughout our application. The syntax is as follows:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/cover-2.png" alt="CSS Variables" width="600" height="400" loading="lazy"></p>
<p>What happens here?<br>Using the <code>--{varName}</code> notation we can tell our browser to store a unique variable called <code>varName</code> (or in the example above, <code>primary</code>), and then we can use it with the <code>var(--{varName})</code> notation anywhere in our <code>.css</code> files.</p>
<p>Does it seem really simple? That's because it is. There's not much to it. According to <a target="_blank" href="https://caniuse.com/#feat=css-variables">caniuse.com</a> over 92% of users world wide use a browser that supports CSS variables (unless you really need IE support, in which case you're out of luck). So for the most part they're completely safe to use.</p>
<p>If you want to read more, you can find more information in the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties">MDN page</a>.</p>
<h2 id="heading-setting-css-variables-from-javascript">Setting CSS Variables from JavaScript</h2>
<p>Setting and using CSS variables from JavaScript is just as easy as setting and using them in CSS. To get a value defined on an element:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> primary = getComputedStyle(element).getPropertyValue(<span class="hljs-string">"--primary"</span>);
</code></pre>
<p>Will give us the value of the <code>primary</code> custom CSS property defined for the <code>element</code>.</p>
<p>Setting a custom CSS property works like so:</p>
<pre><code class="lang-js">element.style.setProperty(<span class="hljs-string">"--light"</span>, <span class="hljs-string">"#5cd2b6"</span>);
</code></pre>
<p>Or, if we want to set the property for the entire application, we can do:</p>
<pre><code class="lang-js"><span class="hljs-built_in">document</span>.documentElement.style.setProperty(<span class="hljs-string">"--light"</span>, <span class="hljs-string">"#5cd2b6"</span>);
</code></pre>
<p>And now the <code>light</code> property will be accessible to all of our code.</p>
<h2 id="heading-react-context-in-a-gist">React Context in a Gist</h2>
<p>The <code>React Context API</code> is the only way provided by React to pass props indirectly from one component to a descendent component. </p>
<p>In this guide I'll use the <code>useContext</code> hook, which you can read more about <a target="_blank" href="https://reactjs.org/docs/hooks-reference.html#usecontext">here</a>. But the principle is the same with class components.</p>
<p>First, we must initialize a context object:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ThemeSelectorContext = React.createContext({
  <span class="hljs-attr">themeName</span>: <span class="hljs-string">"dark"</span>
});
</code></pre>
<p>The parameters passed to the <code>React.createContext</code> function are the default parameters of the context. Now that we have a context object, we can use it to "inject" props to our indirect descendants:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ({ children }) =&gt; (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeSelectorContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">themeName:</span> "<span class="hljs-attr">dark</span>" }}&gt;</span>
    {children}
  <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeSelectorContext.Provider</span>&gt;</span></span>
);
</code></pre>
<p>And now anyone who wants to read the values in our context can do it:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">import</span> { ThemeSelectorContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"./themer"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> () =&gt; {
  <span class="hljs-keyword">const</span> { themeName } = useContext(ThemeSelectorContext);

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>My theme is {themeName}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
};
</code></pre>
<p>A Voilà! No matter where in the component hierarchy our component lies, it has access to the <code>themeName</code> variable. If we want to allow editing the value in our context, we can pass a function like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ({ children }) =&gt; {
  <span class="hljs-keyword">const</span> [themeName, setThemeName] = useState(<span class="hljs-string">"dark"</span>);

  <span class="hljs-keyword">const</span> toggleTheme = <span class="hljs-function">() =&gt;</span> {
    themeName === <span class="hljs-string">"dark"</span> ? setThemeName(<span class="hljs-string">"light"</span>) : setThemeName(<span class="hljs-string">"dark"</span>);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeSelectorContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">themeName</span>, <span class="hljs-attr">toggleTheme</span> }}&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeSelectorContext.Provider</span>&gt;</span></span>
  );
};
</code></pre>
<p>And to use it:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">import</span> { ThemeSelectorContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"./themer"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> () =&gt; {
  <span class="hljs-keyword">const</span> { themeName, toggleTheme } = useContext(ThemeSelectorContext);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>My theme is {themeName}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{toggleTheme}</span>&gt;</span>Change Theme!<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};
</code></pre>
<p>That's enough for our needs, but if you want you can further read on the <a target="_blank" href="https://reactjs.org/docs/context.html">Official React Context Documentation</a>.</p>
<h2 id="heading-putting-everything-together">Putting Everything Together</h2>
<p>Now that we know how to set CSS custom properties from JavaScript, and we can pass props down our component tree, we can make a really nice and simple "theme engine" for our application. First up we'll define our themes:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> themes = {
  <span class="hljs-attr">dark</span>: {
    <span class="hljs-attr">primary</span>: <span class="hljs-string">"#1ca086"</span>,
    <span class="hljs-attr">separatorColor</span>: <span class="hljs-string">"rgba(255,255,255,0.20)"</span>,
    <span class="hljs-attr">textColor</span>: <span class="hljs-string">"white"</span>,
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">"#121212"</span>,
    <span class="hljs-attr">headerBackgroundColor</span>: <span class="hljs-string">"rgba(255,255,255,0.05)"</span>,
    <span class="hljs-attr">blockquoteColor</span>: <span class="hljs-string">"rgba(255,255,255,0.20)"</span>,
    <span class="hljs-attr">icon</span>: <span class="hljs-string">"white"</span>
  },
  <span class="hljs-attr">light</span>: {
    <span class="hljs-attr">primary</span>: <span class="hljs-string">"#1ca086"</span>,
    <span class="hljs-attr">separatorColor</span>: <span class="hljs-string">"rgba(0,0,0,0.08)"</span>,
    <span class="hljs-attr">textColor</span>: <span class="hljs-string">"black"</span>,
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">"white"</span>,
    <span class="hljs-attr">headerBackgroundColor</span>: <span class="hljs-string">"#f6f6f6"</span>,
    <span class="hljs-attr">blockquoteColor</span>: <span class="hljs-string">"rgba(0,0,0,0.80)"</span>,
    <span class="hljs-attr">icon</span>: <span class="hljs-string">"#121212"</span>
  }
};
</code></pre>
<p>This just happens to be the color pallette I use for my blog, but really the sky is the limit when it comes to themes, so feel free to experiment.</p>
<p>Now we create our <code>ThemeSelectorContext</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ThemeSelectorContext = React.createContext({
  <span class="hljs-attr">themeName</span>: <span class="hljs-string">"dark"</span>,
  <span class="hljs-attr">toggleTheme</span>: <span class="hljs-function">() =&gt;</span> {}
});
</code></pre>
<p>And our theme component:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ({ children }) =&gt; {
  <span class="hljs-keyword">const</span> [themeName, setThemeName] = useState(<span class="hljs-string">"dark"</span>);
  <span class="hljs-keyword">const</span> [theme, setTheme] = useState(themes[themeName]);

  <span class="hljs-keyword">const</span> toggleTheme = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (theme === themes.dark) {
      setTheme(themes.light);
      setThemeName(<span class="hljs-string">"light"</span>);
    } <span class="hljs-keyword">else</span> {
      setTheme(themes.dark);
      setThemeName(<span class="hljs-string">"dark"</span>);
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeSelectorContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">toggleTheme</span>, <span class="hljs-attr">themeName</span> }}&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeSelectorContext.Provider</span>&gt;</span></span>
  );
};
</code></pre>
<p>In this component we store our selected theme object, and the selected theme name, and we defined a function to toggle our selected theme.</p>
<p>The last bit left is actually setting the CSS custom properties from our theme. We can easily do it using the <code>.style.setProperty</code> API:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> setCSSVariables = <span class="hljs-function"><span class="hljs-params">theme</span> =&gt;</span> {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> value <span class="hljs-keyword">in</span> theme) {
    <span class="hljs-built_in">document</span>.documentElement.style.setProperty(<span class="hljs-string">`--<span class="hljs-subst">${value}</span>`</span>, theme[value]);
  }
};
</code></pre>
<p>Now for each value in our <code>theme</code> object we can access a CSS property with the same name (prefixed with <code>--</code> of course). The last thing we need is to run the <code>setCSSVariables</code> function every time the theme is toggled. So in our <code>Theme</code> component we can use the <code>useEffect</code> hook like so:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ({ children }) =&gt; {
  <span class="hljs-comment">// code...</span>

  useEffect(<span class="hljs-function">() =&gt;</span> {
    setCSSVariables(theme);
  });

  <span class="hljs-comment">// code...</span>
};
</code></pre>
<p>The full source code can be found <a target="_blank" href="https://github.com/dorshinar/blog/blob/master/src/components/themer/themer.jsx">on github</a>.</p>
<p>Using our theme is super convenient:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.title</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--primary);
}
</code></pre>
<p>And updating our theme is just as easy:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> Toggle <span class="hljs-keyword">from</span> <span class="hljs-string">"react-toggle"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> () =&gt; {
  <span class="hljs-keyword">const</span> { toggleTheme, themeName } = useContext(ThemeSelectorContext);

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Toggle</span> <span class="hljs-attr">defaultChecked</span>=<span class="hljs-string">{themeName</span> === <span class="hljs-string">"dark"</span>} <span class="hljs-attr">onClick</span>=<span class="hljs-string">{toggleTheme}</span> /&gt;</span></span>;
};
</code></pre>
<p>For this example I'm using the <code>Toggle</code> component from <code>react-toggle</code>, but any toggle/button component would do just fine. Clicking the <code>Toggle</code> will call the <code>toggleTheme</code> function, and will update our theme for the entire app, no more configuration needed.</p>
<p>That's it! That's all you need to do to create a super simple, super clean theme engine for your application. If you want to see a real live example, you can check out the <a target="_blank" href="https://github.com/dorshinar/blog/blob/master/src/components/themer/themer.jsx">source code</a> of my blog.</p>
<p>Thank you for reading!</p>
<p>This article was previously published on my blog: <a target="_blank" href="https://dorshinar.me/themes-using-css-variables-and-react-context">dorshinar.me</a>. If you want to read more content, you can check my blog as it would mean a lot to me.</p>
<p>If you want to support me, you can <a href="https://ko-fi.com/L3L116P44" target="_blank"><img src="https://az743702.vo.msecnd.net/cdn/kofi4.png?v=2" alt="Buy Me a Coffee at ko-fi.com" width="600" height="400" loading="lazy"></a></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
