Svelte: Specify Multiple Conditional Class Attributes

I would like to have something like this made possible:

<div 
   class="overflow-scroll h-screen antialiased ..."
   class:whiteTheme="bg-gray-100 text-gray-800 ..."
   class:darkTheme="bg-blue-900 ..."
>
...
</div>

So one set of classes that will always be applied. One set only if whiteTheme is true and another only if darkTheme is true.

I know that i can define a whiteTheme and a darkTheme css class and make it just work like that

<div 
   class="overflow-scroll h-screen antialiased ..."
   class:whiteTheme
   class:darkTheme
>

But the point is that i want to design each element individual (esp. in the starting phase of my application). And having to define my set of classes for each element in a different class... defies for me the purpose in using Tailwind.css and experimenting on the specific elements (without jumping back and forth between css definitions and element definitions).

Another way i could choose is this:

<div 
   class="overflow-scroll h-screen antialiased ... {whiteTheme?'bg-gray-100 text-gray-800 ...':'bg-blue-900 ...'}">

This is kind of ok, but i would love to increase readability and maintainability by defining things in separate attributes...

So i'm wondering if there is a way to make it work the way i want to... E.g. can i extend the Svelte compiler for that easily ?

best Johannes

5 Answers

You are close with one of your proposals, but it does the opposite of what you want: class:something={condition}

This will apply the something class when the condition is met.

So in your case you would have to do

class:bg-gray-100={whiteTheme}
class:text-gray-800={whiteTheme}

As an alternative you could do

<script>
 $: whiteThemeClasses = whiteTheme ? "gray text..." : "";
 ...
...class=" fixedclasses {whiteThemeClasses} {blackThemeClasses}
1

You could place the classlist for light and dark into string variables and switch between those with a ternary based on the truthiness of the variable darkTheme in a store so it updates all components on change.

It allows for you to style each component individually for light and dark themes, increases readability quite a bit since a space separated string is similar to what we're used to seeing with css, and you can bring the class list up to the top of each component to maintain visibility/ease of access.

<script>
    let light = 'bg-gray-100 text-gray-800 shadow-xl';
    let dark = 'bg-blue-900 text-white';
    
    import { darkTheme } from './store.js';
</script>

<div class="overflow-scroll h-screen p-3 {$darkTheme? dark : light}" >
...
</div>

EDIT:

**This only applies to Tailwind users, not if you're still trying to conditionally apply multiple classes.

Tailwind 2 now takes care of this for us with dark classes.

First you need to switch on manual toggling of dark mode in your tailwind.config.js file.

Then You can conditionally apply the dark class to a single top level container and all components nested inside can use the dark:class-name and it will apply the dark theme. No need to pass state or import your store with dark variable into every component.

Here's a REPL using a fixed stylesheet since Tailwind 2 CDN does not ship darkMode as class.

1

Ok, after some more digging i decided to go with the following patterns:

  • Use the Tailwind plugin . This kind of solution keeps things on the tailwind level (in that perspective it's good). Code looks like
<div 
   class="overflow-scroll 
          h-screen 
          antialiased 
          ... 
          bg-gray-100 
          text-gray-800
          ...
          dark:bg-blue-900
          dark:text-yellow-200
          ..."
>
...
</div>
  • This is pretty good for all "static" styling. With dynamic things like an active/selected element, i settled with using styles:
import { darkTheme } from '../stores.js';
...
<div
    class:selected
    class:$darkTheme
...
<style>
.selected {
    // all common styles
    @apply cursor-default;

    // all light styles
    @apply text-blue-600;
    @apply border-blue-600;
}

.selected.\$darkTheme {
    // all dark styles
    @apply text-yellow-700;
    @apply border-yellow-700;
}
</style>

I figured for smaller components using the styles is not to bad. However i still would find the possibility of defining custom task in Svelte intriguing... or a changed syntax like class:true/false={my classes ...}

Some additional notes:

  • Similar to the plugin I found a nice blog post which yields kind of the same results by just using a custom screen definition: .

    • However this solely relies on a media query, so if you wanna have a custom light/dark switch in your app... i found no way for it.

    • The benefit using this approach however is that you can use @apply in combination with it, which you cannot using the plugin... currently ().

1

You could do something like this:

<h1 class="text-black dark:text-white">Hello world!</h1>

Just follow this tutorial here!

Do this like that:

className={`block text-sm font-medium leading-5 ${
            dark ? 'text-gray-800' : 'text-gray-300'
          }`}

This is just an example of conditional class formatting, you can modify it with your condition and property style variables

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Maya Lin-Takahashi

Maya Lin-Takahashi

Consumer Tech & Gadget Reviewer

Maya is a hardware enthusiast who tests and reviews smart home devices, smartphones, wearables, and audio gear. She focuses on practical consumer value and build quality.

Share this article
Twitter Facebook Pinterest