<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://foundata.com/" xml:lang="en"><title>Tailwind-Css on foundata</title><id>https://foundata.com/en/tags/tailwind-css/feed-atom.xml</id><link rel="self" type="application/atom+xml" hreflang="en" href="https://foundata.com/en/tags/tailwind-css/feed-atom.xml" title="atom"/><link rel="alternate" type="text/html" hreflang="en" href="https://foundata.com/en/tags/tailwind-css/" title="html"/><link rel="alternate" type="application/rss+xml" hreflang="en" href="https://foundata.com/en/tags/tailwind-css/feed-rss.xml" title="rss"/><link rel="alternate" type="application/atom+xml" hreflang="de" href="https://foundata.com/de/tags/tailwind-css/feed-atom.xml" title="atom, Deutsch"/><link rel="alternate" type="text/html" hreflang="de" href="https://foundata.com/de/tags/tailwind-css/feed-atom.xml" title="html, Deutsch"/><link rel="alternate" type="application/rss+xml" hreflang="de" href="https://foundata.com/de/tags/tailwind-css/feed-atom.xml" title="rss, Deutsch"/><updated>2023-08-28T17:06:00Z</updated><author><name>foundata GmbH</name><email>webmaster@foundata.com</email><uri>https://foundata.com/</uri></author><rights>© 2023-2026, foundata GmbH (https://foundata.com)</rights><icon>https://foundata.com/images/feed-icon.67ff83c698af1511552374e80cf5f6ff26d497ef21f04186cf058859d535ca75.svg</icon><logo>https://foundata.com/images/feed-logo.9138f24a120dabc7e3d34003662131cc9c7f2ff153ec39d2f6dea3a48c35b4bf.svg</logo><entry><title type="html">How to use Tailwind CSS v3 in Hugo themes (including live reload)</title><id>tag:foundata.com,2023-08-28:/en/blog/2023/hugo-theme-tailwind-css-jit-livereload/</id><published>2023-08-28T17:06:00Z</published><updated>2023-08-28T17:06:00Z</updated><link href="https://foundata.com/en/blog/2023/hugo-theme-tailwind-css-jit-livereload/?utm_source=feed-atom" rel="alternate" type="text/html"/><link href="https://foundata.com/de/blog/2023/hugo-theme-tailwind-css-jit-livereload/?utm_source=feed-atom" rel="alternate" type="text/html" hreflang="de"/><author><name>Andreas Haerter</name><uri>https://andreashaerter.com/</uri></author><summary type="html">Tips for using Tailwind CSS v3.x and its JIT compiler in Hugo Themes, including live reload.</summary><content type="html" xml:base="https://foundata.com/"><![CDATA[<p>We redesigned <a href="https://foundata.com/en/" target="_blank" rel="noreferrer noopener">foundata.com</a> in August 2023 and now use the <a href="https://en.wikipedia.org/wiki/Static_site_generator" target="_blank" rel="noreferrer noopener">Static Site Generator</a> <a href="https://gohugo.io/" target="_blank" rel="noreferrer noopener">Hugo</a>. The theme developed for the site is using <a href="https://tailwindcss.com/blog/tailwindcss-v3" target="_blank" rel="noreferrer noopener">Tailwind CSS v3</a> as CSS framework.</p>
<p>But enough with corporate talk about the awesomeness of our website relaunch 😃, let me share some tips for Hugo theme developers who also want to use Tailwind CSS v3.x and its <a href="https://tailwindcss.com/blog/just-in-time-the-next-generation-of-tailwind-css" target="_blank" rel="noreferrer noopener">JIT-Compiler</a>.</p>
<p>There are a lot of useful resources about Hugo and Tailwind CSS on the web.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> However, there is still little information about how to use Tailwind CSS v3.x and its JIT compiler when developing a Hugo theme. In particular, descriptions of how to setup a development mode with live reload for both are rarely found. I will therefore show how we implemented this in our Hugo template.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<h2 id="sample-page-including-live-reload-on-changes-with-hugo-server" class="scroll-mt-20 md:scroll-mt-24 wrap-break-word group/heading "><a href="#sample-page-including-live-reload-on-changes-with-hugo-server" class="group-hover/heading:after:content-['#'] group-hover/heading:after:ml-1.5 group-hover/heading:after:text-content-400" id="sample-page-including-live-reload-on-changes-with-hugo-server">Sample page including live reload on changes with <code>hugo server</code></a></h2><p><a href="https://gohugo.io/commands/hugo_server/" target="_blank" rel="noreferrer noopener">Hugo offers a built-in web server.</a>. This is especially useful when developing a template, as it automatically injects <a href="https://github.com/livereload/livereload-js" target="_blank" rel="noreferrer noopener">liverelaod-js</a> into the pages. So it does not only re-generate the pages when changes are made, but the browser also loads the new content automatically. As a developer, you can simply leave your browser open, save a change to the template or the example content and the page reloads directly. A nice development experience.</p>
<p>The content directory and the theme to be used can be defined using the parameters <code>--source</code> and <code>--themesDir</code>. This allows you to manage a complete sample website including configuration, which uses all the features of the theme and provides different text lengths etc. pp. to optimize the typography during development. We did this under <code>exampleSite</code>.</p>
<p>I use the following call to start the web server with our sample content and theme (an explanation of each parameter can be found in the <a href="https://gohugo.io/commands/hugo_server/" target="_blank" rel="noreferrer noopener">documentation on <code>hugo server</code></a>) :</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">hugo server <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --source ./exampleSite <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --themesDir ../.. <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --baseURL http://localhost/ <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --port <span class="m">1313</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --buildDrafts <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --cleanDestinationDir <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --logLevel debug <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --disableFastRender <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --gc <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --minify <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --noHTTPCache <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --printI18nWarnings <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --templateMetrics <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --templateMetricsHints
</span></span></code></pre></div><p>Please note: <code>--logLevel debug</code> was introduced with <a href="https://github.com/gohugoio/hugo/releases/tag/v0.114.0" target="_blank" rel="noreferrer noopener">v0.114.0</a>. If your Hugo version is older, you have to use <code>--debug</code> instead.</p>
<h2 id="re-generate-the-tailwind-css-styles-on-changes-via-jit-compiler" class="scroll-mt-20 md:scroll-mt-24 wrap-break-word group/heading "><a href="#re-generate-the-tailwind-css-styles-on-changes-via-jit-compiler" class="group-hover/heading:after:content-['#'] group-hover/heading:after:ml-1.5 group-hover/heading:after:text-content-400" id="re-generate-the-tailwind-css-styles-on-changes-via-jit-compiler">Re-generate the Tailwind CSS styles on changes via JIT compiler</a></h2><p>Tailwind CSS is typically <a href="https://tailwindcss.com/docs/installation" target="_blank" rel="noreferrer noopener">installed via NodeJS</a>. The <code>npx tailwindcss</code> command also provides file change monitoring (<code>--watch</code> parameter) with automatic style regeneration via <a href="https://tailwindcss.com/blog/just-in-time-the-next-generation-of-tailwind-css" target="_blank" rel="noreferrer noopener">JIT-Compiler</a>.</p>
<p>The CSS source file of our Hugo theme is located at <code>./assets/styles/tw-main-src.css</code>, the output file is generated at <code>./assets/styles/tw-main-dist.css</code>. The following command is used for this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">NODE_ENV</span><span class="o">=</span>development npx tailwindcss <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  -i ./assets/styles/tw-main-src.css <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  -o ./assets/styles/tw-main-dist.css <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --watch --minify
</span></span></code></pre></div><p>The <code>tailwind.config.js</code> file defines which directories of the Hugo template should be searched for styles. In our template it looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="c1">//[...]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="err">module.exports</span> <span class="err">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="err">/*</span> <span class="err">Content</span> <span class="err">sources</span> <span class="err">to</span> <span class="err">tell</span> <span class="err">Tailwind</span> <span class="err">which</span> <span class="err">files</span> <span class="err">to</span> <span class="err">scan</span> <span class="err">for</span> <span class="err">used</span> <span class="err">class</span> <span class="err">names</span> <span class="err">for</span>
</span></span><span class="line"><span class="cl">     <span class="err">generating</span> <span class="err">the</span> <span class="err">needed</span> <span class="err">CSS.</span> <span class="err">More</span> <span class="err">info:</span>
</span></span><span class="line"><span class="cl">     <span class="err">-</span> <span class="err">https:</span><span class="c1">//tailwindcss.com/docs/content-configuration#configuring-source-paths
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="err">*/</span>
</span></span><span class="line"><span class="cl">  <span class="err">content:</span> <span class="err">[</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;./layouts/**/*.html&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;./content/**/*.{html,md}&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;./themes/foundata/layouts/**/*.html&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;./exampleSite/**/*.{html,md}&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="err">],</span>
</span></span><span class="line"><span class="cl">  <span class="c1">//[...]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>In the file <code>./themes/foundata/layouts/_default/baseof.html</code> the following lines are responsible for loading the generated CSS file:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-golang" data-lang="golang"><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="cm">/* Use a Hugo scratch to store files and content for bundling CSS and JS assets */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">assets</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">newScratch</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="cm">/* TailwindCSS */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">assets</span><span class="p">.</span><span class="nx">Add</span><span class="w"> </span><span class="s">&#34;css&#34;</span><span class="w"> </span><span class="p">(</span><span class="nf">slice</span><span class="w"> </span><span class="p">(</span><span class="nx">resources</span><span class="p">.</span><span class="nx">Get</span><span class="w"> </span><span class="s">&#34;styles/tw-main-dist.css&#34;</span><span class="p">))</span><span class="w"> </span><span class="p">}}</span><span class="w"> </span><span class="p">{{</span><span class="cm">/* output file for distribution */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">[</span><span class="o">...</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="cm">/* Get the scratch&#39;s CSS content as bundled, optimized file */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="err">$</span><span class="nx">assets</span><span class="p">.</span><span class="nx">Get</span><span class="w"> </span><span class="s">&#34;css&#34;</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">bundleCSS</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">assets</span><span class="p">.</span><span class="nx">Get</span><span class="w"> </span><span class="s">&#34;css&#34;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="nx">resources</span><span class="p">.</span><span class="nx">Concat</span><span class="w"> </span><span class="s">&#34;styles/bundle.css&#34;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="nx">resources</span><span class="p">.</span><span class="nx">Minify</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="nx">resources</span><span class="p">.</span><span class="nx">Fingerprint</span><span class="w"> </span><span class="s">&#34;sha256&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">&lt;</span><span class="nx">link</span><span class="w"> </span><span class="kd">type</span><span class="p">=</span><span class="s">&#34;text/css&#34;</span><span class="w"> </span><span class="nx">rel</span><span class="p">=</span><span class="s">&#34;stylesheet&#34;</span><span class="w"> </span><span class="nx">href</span><span class="p">=</span><span class="s">&#34;{{ $bundleCSS.RelPermalink }}&#34;</span><span class="w"> </span><span class="nx">integrity</span><span class="p">=</span><span class="s">&#34;{{ $bundleCSS.Data.Integrity }}&#34;</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span></code></pre></div><h2 id="use-everything-together-via-packagesjson" class="scroll-mt-20 md:scroll-mt-24 wrap-break-word group/heading "><a href="#use-everything-together-via-packagesjson" class="group-hover/heading:after:content-['#'] group-hover/heading:after:ml-1.5 group-hover/heading:after:text-content-400" id="use-everything-together-via-packagesjson">Use everything together via <code>packages.json</code></a></h2><p>There is a <code>packages.json</code> in the root of our template as the Tailwind CSS installation is managed via NodeJS. It can also be used to comfortably merge the above commands.</p>
<p>We have placed them into individual <code>scripts</code> that can be called via <code>npm run &lt;name&gt;</code>. The <a href="https://www.npmjs.com/package/npm-run-all" target="_blank" rel="noreferrer noopener"><code>npm-run-all</code> package</a> gives us the possibility to concatenate everything without deadlocks. In our <code>packages.json</code>, it looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="c1">//[...]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;hugo-foundata-theme&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;version&#34;</span><span class="p">:</span> <span class="s2">&#34;1.0.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;foundata theme for Hugo&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;scripts&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="err">[...]</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;dev&#34;</span><span class="p">:</span> <span class="s2">&#34;npm-run-all --parallel dev:tailwindcss dev:example --print-name --race&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;dev:tailwindcss&#34;</span><span class="p">:</span> <span class="s2">&#34;touch ./assets/styles/tw-main-dist.css &amp;&amp; NODE_ENV=development npx tailwindcss -i ./assets/styles/tw-main-src.css -o ./assets/styles/tw-main-dist.css --watch --minify&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;dev:example&#34;</span><span class="p">:</span> <span class="s2">&#34;hugo server --source ./exampleSite --themesDir ../.. --baseURL http://localhost/ --port 1313 --buildDrafts --cleanDestinationDir --disableFastRender --gc --minify --noHTTPCache --printI18nWarnings --templateMetrics --templateMetricsHints&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;build:vendorlibs&#34;</span><span class="p">:</span> <span class="s2">&#34;npm-run-all preinstall postinstall --print-name&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;build:tailwindcss&#34;</span><span class="p">:</span> <span class="s2">&#34;NODE_ENV=production npx tailwindcss -i ./assets/styles/tw-main-src.css -o ./assets/styles/tw-main-dist.css --minify&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="c1">//[...]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>That&rsquo;s it. To work on the theme, simply change into the theme directory, run <code>npm run dev</code> and access the Hugo example page at <code>http://localhost:1313</code>. It is automatically regenerated on every change to a style, <a href="https://gohugo.io/templates/" target="_blank" rel="noreferrer noopener">template</a> or sample content. It then gets automatically reloaded in the browser. This is particularly reasonable given Tailwind CSS&rsquo;s <a href="https://adamwathan.me/css-utility-classes-and-separation-of-concerns/" target="_blank" rel="noreferrer noopener">utility-first</a> approach.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Besides the official documentation, I found <a href="https://www.regisphilibert.com/tags/hugo/" target="_blank" rel="noreferrer noopener">https://www.regisphilibert.com/tags/hugo/</a> really helpful.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://github.com/gohugoio/hugo/releases/tag/v0.112.0" target="_blank" rel="noreferrer noopener">Hugo version v0.112.0</a> also introduced an option to integrate Tailwind CSS v3.x in a better way. But we take a slightly different approach.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content><category scheme="taxonomy:tags" term="foundata" label="foundata"/><category scheme="taxonomy:tags" term="webdev" label="webdev"/><category scheme="taxonomy:tags" term="hugo" label="hugo"/><category scheme="taxonomy:tags" term="tailwind-css" label="tailwind-css"/></entry></feed>