Skip to content

Styling

Datastar provides attributes for controlling CSS classes and inline styles dynamically based on signal values. These attributes let you create responsive interfaces that change appearance as your application state changes, without writing JavaScript event handlers or DOM manipulation code.

Conditional Classes

data-class:* (Datastar)

The data-class:* attribute adds or removes a CSS class based on whether an expression evaluates to true. Replace * with the class name you want to control:

blade
<div data-signals="{isActive: true}">
    <button data-class:active="$isActive">
        Click Me
    </button>
</div>

When isActive is true, the button has the active class. When isActive becomes false, the class is removed automatically.

Multiple Classes

You can control multiple classes independently:

blade
<div data-signals="{
    isDisabled: true,
    hasError: false
}">
    <button
        data-class="{
            'cursor-not-allowed': $isDisabled,
            'text-red-500': $hasError
        }"
        class="px-4 py-2 rounded">
        Submit
    </button>
</div>

Expressions

The condition can be any JavaScript expression:

blade
<div data-signals="{count: 12}">
    <div 
    data-class="{'bg-yellow-500 text-white': $count > 10}">
        Count: <span data-text="$count"></span>
    </div>
</div>

The bg-yellow-500, text-white classes are added when count exceeds 10.

Multiple Class Names

You can add or remove multiple classes together by separating them with spaces:

blade
<div data-signals="{isPremium: true}">
    <div 
    data-class="{'bg-amber-600 text-white font-bold': $isPremium}"
    >
        Premium Content
    </div>
</div>

When isPremium is true, all three classes (bg-amber-600, text-white, font-bold) are added. When false, all are removed.

Dynamic Inline Styles

data-style:* (Datastar)

The data-style:* attribute sets inline CSS properties dynamically. Replace * with the CSS property name:

blade
<div data-signals="{progress: 75}">
    <div
        data-style:width="$progress + '%'"
        class="bg-blue-500 h-4 rounded">
    </div>
</div>

As progress changes, the width style updates immediately. Use standard CSS property names in kebab-case.

Multiple Style Properties

Control different properties independently:

blade
<div data-signals="{
    boxColor: 'blue',
    boxSize: 100,
    boxOpacity: 0.8
}">
    <div
        data-style:background-color="$boxColor"
        data-style:width="$boxSize + 'px'"
        data-style:height="$boxSize + 'px'"
        data-style:opacity="$boxOpacity">
    </div>
</div>

Conditional Styles

Use ternary operators to conditionally set styles:

blade
<div data-signals="{theme: 'dark'}">
    <div data-style:color="$theme === 'dark' ? 'white' : 'black'"
         data-style:background-color="$theme === 'dark' ? '#1a1a1a' : '#ffffff'">
        Content adapts to theme
    </div>
</div>

Common Patterns

blade
<div data-signals="{currentPage: 'home'}">
    <nav>
        <a href="/home"
           data-class:active="$currentPage === 'home'"
           data-on:click="$currentPage = 'home'">
            Home
        </a>
        <a href="/about"
           data-class:active="$currentPage === 'about'"
           data-on:click="$currentPage = 'about'">
            About
        </a>
        <a href="/contact"
           data-class:active="$currentPage === 'contact'"
           data-on:click="$currentPage = 'contact'">
            Contact
        </a>
    </nav>
</div>

<style>
    .active {
        font-weight: bold;
        color: blue;
        border-bottom: 2px solid blue;
    }
</style>

Form Validation States

blade
<div data-signals="{
    email: '',
    errors: {}
}">
    <input
        type="email"
        data-bind="email"
        data-class:border-red-500="$errors.email"
        data-class:border-gray-300="!$errors.email"
        class="border-2 rounded px-3 py-2" />

    <div data-error="email" class="text-red-500 text-sm"></div>
</div>

The input border turns red when there's an error, gray otherwise.

Loading States

blade
<div data-signals="{isLoading: false}">
    <button
        data-class:opacity-50="$isLoading"
        data-class:cursor-not-allowed="$isLoading"
        data-attr:disabled="$isLoading"
        data-on:click="$isLoading = true">
        <span data-show="!$isLoading">Submit</span>
        <span data-show="$isLoading">Processing...</span>
    </button>
</div>

Theme Switching

blade
<div data-signals="{theme: 'dark'}">
    <div
        data-class="{
            'bg-white text-black': $theme === 'light',
            'bg-gray-900 text-white': $theme === 'dark'
        }" class="min-h-screen p-8">
        

        <button
            data-on:click="$theme = ($theme === 'light' ? 'dark' : 'light')"
            class="px-4 py-2 rounded cursor-pointer">
            Toggle Theme 
        </button>
        <div>Current: <span data-text="$theme"></span></div>

        <div class="mt-8">
            <h1 class="text-3xl font-bold">Themed Content</h1>
            <p class="mt-4">This content adapts to the current theme.</p>
        </div>
    </div>
</div>

Status Indicators

blade
<div data-signals="{status: 'pending'}">
    <span
        class="px-3 py-1 rounded-full text-sm font-medium transition-all duration-300"
        data-class="{
            'bg-yellow-100 text-yellow-800': $status === 'pending',
            'bg-green-100 text-green-800': $status === 'completed',
            'bg-red-100 text-red-800': $status === 'failed'
        }">
        <span data-text="$status"></span>
    </span>
</div>

Hover Effects with State

blade
<div data-signals="{isHovered: false}">
    <div
        data-on:mouseenter="$isHovered = true"
        data-on:mouseleave="$isHovered = false"
        data-class:shadow-lg="$isHovered"
        data-class:scale-105="$isHovered"
        class="p-6 border rounded transition-all duration-300">
        Hover over me
    </div>
</div>

Working with Tailwind CSS

Datastar's styling attributes work seamlessly with Tailwind CSS:

blade
<div data-signals="{priority: 'high'}">
    <div
        class="text-black px-4 py-2 rounded"
        data-class="{
            'bg-red-500': $priority === 'low',
            'bg-yellow-500': $priority === 'medium',
            'bg-green-500': $priority === 'high'
        }">
        Priority: <span data-text="$priority"></span>
    </div>
</div>

Dark Mode

Combine with Tailwind's dark mode classes:

blade
<div data-signals="{darkMode: false}">
    <div data-class:dark="$darkMode">
        <div class="bg-white dark:bg-gray-800 text-black dark:text-white p-8">
            This content respects dark mode
        </div>
    </div>
</div>

Learn More