Tailwind CSS + SvelteKit = ❤️ && 💔 – closingtags </>
Categories
CSS Javascript Programming Svelte SvelteKit

Tailwind CSS + SvelteKit = ❤️ && 💔

In an effort to promote my upcoming book, I created the website https://sveltekitbook.dev. It has all of the information one may want to know before purchasing a copy. Of course, the book is about #SvelteKit so I had to build the site using #SvelteKit. I decided to take the opportunity to learn the latest technology web developers can’t shut up about; #TailwindCSS.

What’s the deal with Tailwind CSS anyways?

I’m sure you’ve heard of Bootstrap. Well Tailwind CSS is kind of like Bootstrap. They’re the same in that they’re both useful for developers that suck at CSS reducing the amount of CSS you’ll need to write manually. Both provide classes that can be applied to HTML elements but Tailwind CSS is a utility-first CSS framework while Bootstrap is an entire front-end framework that comes with pre-built components. I won’t go on to list the various differences here because its been done to death by this point. But the main takeaway from Tailwind CSS is that if you want to apply a style to an element, you give that element the corresponding class to the style rule. That includes everything from colors, padding, display, height, etc.

For example, if I wanted to set the color of text in a link element as well as ensure the text is underlined on hover, I would do that like so:

<a href='text-lime-500 hover:underline'>lime color link!</a>

❤️

So why won’t web developers shut up about Tailwind CSS? Well there’s a few reasons. For one, I found that it was incredibly lightweight. When coupled with Vite; the bundling tool used by SvelteKit, only the applied styles are included. This means that all of the extra styles available with the framework are tree-shaken out so nothing unused is delivered to the client. This is great for performance reason as it reduces the amount of content delivered over the network.

Another quality about Tailwind CSS that I enjoyed was the utility-first approach. I won’t lie, it took me a while to get used to it. I’ve used Bootstrap in the past which is what I was expecting Tailwind CSS to be like. But where Bootstrap comes with so many classes that it can be hard to remember when to use which ones, Tailwind CSS classes are just the names of the style rules you’d like to apply. So while Tailwind CSS may include more labor upfront, it does seem to offer more granular control than the likes of Bootstrap. And once you get used to the utility-first methodology, applying styles becomes as easy as writing CSS except that you never have to leave the markup!

I also really enjoyed the mobile first strategy provided with Tailwind CSS. It’s achieved by prefixing classes with modifiers like sm: or md:. This ensures that any styles not given the prefix are always applied, even on the smallest of screens. When given the modifier prefix, the styles are adjusted for the corresponding screen width. The sane defaults provided by Tailwind CSS makes developing for mobile devices effortless.

💔

Of course, it wasn’t all love at first sight. When building a site with SvelteKit, each component just so happens to be a Svelte component. That’s kind of the whole reason anyone uses SvelteKit, right? And Svelte components already have a method for including styles inside <style></style> tags. So now I’m just supposed to ignore those tags?!

Well yes, but also no. There were a few times I noticed that Tailwind CSS couldn’t quite do everything I wanted and in those instances, I fell back to using good old fashioned <style></style> tags.

For instance, I wanted to apply a linear gradient like so:

An orange rectangle with a 50 degree slant at the 75% interval, changing to a slightly darker orange.

While Tailwind CSS can do linear gradients, they’re very rigid and not flexible enough to achieve this slanted effect which makes use of CSS calc(). At first, I just dumped the appropriate CSS into the <style></style> of my component. But I wanted to use it in multiple components so I needed to find a way to make that style portable. Since styles added in a Svelte component exist only in that component; just like wealth, those styles will never “trickle down.” In instances like this, I would normally write one CSS class in a global stylesheet and be done with it. Lucky for me, there exists a Tailwind CSS official workaround which involves extending the base theme with my very own highly-customized gradient style. To do this, I had to modify tailwind.config.js.

tailwind.config.js

export default {
  content: ['./src/**/*.{html,js,svelte,ts}'],
  theme: {
    extend: {
      backgroundImage: {
        'gradient-o': 'linear-gradient(45deg, #f97141 50%, #1a1a1a80 calc( 50% + 2px ))'
      },
    },
  },
  plugins: [],
}

I can then go on to use the class gradient-o in the HTML elements as if it were a utility provided by Tailwind CSS.

But that wasn’t the only issue I had. I also hated how my markup began to look with so many classes applied to each element. It can quickly become cumbersome to search all of the classes applied when attempting to make minor style changes. In good old fashioned CSS, one simply needs to locate a single class definition and adjust the rules accordingly. An example of this frustration became more glaring whenever I created a link element (<a></a>). With each new link, I’d then have to ensure it contained the exact same classes as all the others. And I often forgot to include classes which led to inconsistencies across the site. My initial plan to address this was by creating a Link.svelte component. This likely would have addressed the issue but it seemed silly to create a whole component for something as trivial as links.

Of course, there was an even simpler method. When including Tailwind CSS in a SvelteKit project, you need to create a main CSS (src/app.css) file. This file then imports all of the Tailwind CSS styles and can be included in the SvelteKit main layout (src/+layout.svelte) which guarantees that all class definitions can be applied throughout the project. It is in this main CSS file that we can override the default styles provided by Tailwind CSS. In mine, I also included a custom web font that is applied to the entirety of the HTML document.

src/app.css

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  html {
    font-family: 'Outfit', sans-serif;
    src: url('/src/lib/assets/Outfit.ttf');
  }
  p > a {
    @apply text-amber-600 hover:text-amber-800 hover:underline;
  }
}

This snippet rule p > a means that all links (<a></a>) directly inside of a paragraph (<p></p>) tag will have the same styles applied throughout the project. No more repeating the same three styles over and over again.

To use or not to use?

Will I use Tailwind CSS again? Yeah, probably. It did reduce the amount of CSS I wrote and made working with flexbox and grid containers incredibly simple. For all of those things that Tailwind CSS can’t do, I can always fall back to writing CSS directly in my Svelte components. And now that I’ve worked out the kinks to reduce applying styles to every link or paragraph tag, there’s a lot less friction and clutter in my markup.

If you want to try combining SvelteKit and Tailwind CSS, you can follow the official documentation provided by Tailwind CSS. It’s a few steps but is fairly straightforward.

Or you can save yourself a ton of time and use this adder from the Svelte community resources. It’s as simple as running the following command:

npx svelte-add@latest tailwindcss

And just like that, your SvelteKit project now has Tailwind CSS support.

If you enjoyed this article, consider buying my new book! You can find more information about it at sveltekitbook.dev. And if you want to see the source code for that site, it can be viewed at https://github.com/Dilden/sveltekitbook.dev.

By Dylan Hildenbrand

Author and full stack web developer experienced with #PHP, #SvelteKit, #JS, #NodeJS, #Linux, #WordPress, and #Ansible. Check out my book at sveltekitbook.dev!

Do you like these posts? Consider sponsoring me on GitHub!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.