12
votes

In Svelte, how should classes be changed on elements depending upon component state?

For instance, you may wish to apply a class to a button under certain conditions, as in the following example.

<button class="{{class}}">

Right now, this can be achieved by creating a computed property which would return class names, or empty strings, under certain conditions.

However, I am concerned over whether this might be polluting the computed properties namespace. For instance, if there were a status, it might be desired to both set a dynamic text, like statusMessage, and a class, like statusClass.

Is there a better way to do this, or are computed properties the way to go? Is any more explicit support for CSS planned for Svelte?

5

5 Answers

12
votes

You can use an inline expression, like so:

<button class='{{active ? "active": "inactive"}}'>
  {{active ? 'Selected' : 'Select this'}}
</button>

That's generally better than using a computed property, because it's immediately clear what the possible values are just by looking at the template.

You can also use helper functions, if the expression would become unwieldy — in some situations you might prefer these to computed values:

<button class='{{getClass(status)}}'>{{getText(status)}}</button>

<script>
  export default {
    helpers: {
      getClass(status) {
        // ...
      },
      getText(status) {
        // ...
      }
    }
  };
</script>
11
votes

Today you can use:

export let whitetext = false;
<div class:whitetext></div>

and then

<MyComponent whitetext={true} />

syntax for simple true/false based classes.

3
votes

There's no inbuilt way to do use, eg, conditionals {#if} inside class=, per other popular frameworks.

Since inline expressions will become unweildy as soon as you have more than two classes, I'd go stright to helpers in that case. Quick example of a class builder helper:

helpers: {
    getSlideClasses(index, currentIndex) {
        let classes = ['js_slide']
        if ( index === currentIndex ) {
            classes.push('selected')
        }
        if ( index === 0 ) {
            classes.push('first')
        }
        return classes.join(' ')
    }
}

And then:

<div class='{ getSlideClasses(index, currentIndex)}'>
3
votes

According to the tutorial it's:

<div class:active="{current === 'foo'}">

If the condition returns true, then the active class is added.

See: https://svelte.dev/tutorial/classes

1
votes

From the docs: https://svelte.dev/tutorial/classes

<script>
    let current = 'foo';
</script>

<style>a
    button {
        display: block;
    }

    .active {
        background-color: #ff3e00;
        color: white;
    }
</style>

<button
    class="{current === 'foo' ? 'active' : ''}"
    on:click="{() => current = 'foo'}"
>foo</button>

<button
    class="{current === 'bar' ? 'active' : ''}"
    on:click="{() => current = 'bar'}"
>bar</button>

<button
    class="{current === 'baz' ? 'active' : ''}"
    on:click="{() => current = 'baz'}"
>baz</button>