Svelte: Specify multiple conditional class attributes

I would like to have something like this made possible:

<div 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: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> 

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 > ... </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 > ... </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>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

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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.

You Might Also Like