Laravel and Livewire change button style on click

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering Dynamic UI: Changing Button Styles with Laravel Livewire and Tailwind CSS

As senior developers working within the Laravel ecosystem, we frequently encounter the need for dynamic user interfaces—situations where the appearance or behavior of an element must change based on user interaction. A common scenario involves toggling states, like switching between "Add" mode and "Set" mode, which necessitates changing CSS classes dynamically.

The challenge you've presented—switching between blue and gray button styles upon clicking—is a classic example of state management in web development. While pure HTML and CSS handle static presentation beautifully, making those styles react to user actions requires a mechanism to track the current state and update the DOM accordingly. This is where frameworks like Laravel Livewire truly shine, allowing us to bridge the gap between server-side logic (Laravel) and front-end interactivity (Tailwind CSS).

The Challenge: Static vs. Dynamic Styling

The provided HTML shows two buttons with distinctly different Tailwind classes: one blue (bg-blue-500) and one gray (bg-gray-50). To switch these states, we need a mechanism to tell the browser which set of classes to apply. If we rely solely on vanilla JavaScript, we can achieve this by listening for the click event and toggling CSS classes directly. However, when working within a Laravel context, especially with Livewire, managing this state on the server side provides a more robust and maintainable solution.

The Solution: Leveraging Livewire State Management

In a Laravel application utilizing Livewire, we manage dynamic UI changes by tracking a piece of data—the state—within the Livewire component. When the user clicks a button, it triggers an action that updates this state on the server. Livewire then automatically re-renders the component on the front end with the new state, applying the correct Tailwind classes based on that data.

Step 1: Define the State in the Livewire Component

We introduce a boolean property (e.g., $isSet) into our Livewire component to track which mode the user is currently in.

php
// app/Http/Livewire/ButtonToggle.php

namespace App\Http\Livewire;

use Livewire\Component;

class ButtonToggle extends Component
{
    public bool $isSet = false; // Initial state: 'Add' mode

    public function toggleMode()
    {
        // Toggling the state when the button is clicked
        $this->isSet = !$this->isSet;
    }

    public function render()
    {
        return view('livewire.button-toggle');
    }
}

Step 2: Conditionally Apply Tailwind Classes in the Blade View

In the Blade file, we use standard PHP conditional syntax (@if) to check the value of $isSet and apply the appropriate Tailwind classes to the buttons. This ensures that the presentation perfectly reflects the underlying data state.

html
{{-- resources/views/livewire/button-toggle.blade.php --}}

<div class="flex flex-row">

    {{-- 'Add' Button Styling --}}
    <button 
        class="ml-px relative inline-flex items-center space-x-2 px-4 py-4 border border-blue-300 text-sm font-medium rounded-l-md text-white bg-blue-500 hover:bg-blue-600 focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-blue-500"
    >
        <span>Add</span>
    </button>

    {{-- 'Set' Button Styling (Conditional) --}}
    <button 
        class="ml-px relative inline-flex items-center space-x-2 px-4 py-4 border border-gray-300 text-sm font-medium text-gray-900 bg-gray-50 hover:bg-gray-100 focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-blue-500"
        {{-- Apply the 'Set' style only when $isSet is true --}}
        @if ($isSet)
            class="bg-blue-500 hover:bg-blue-600 focus:ring-indigo-500"
        @else
            class="bg-gray-50 hover:bg-gray-100 focus:ring-indigo-500"
        @endif
    >
        <span>Set</span>
    </button>

</div>

Note on the Example Above: While the example above shows a complex conditional structure, for cleaner class toggling with Tailwind, it is often simpler to define two distinct sets of classes and use the $isSet variable to switch between them entirely. A more streamlined approach would be:

html
{{-- Simplified Conditional Styling Approach --}}
<button 
    class="{{ $isSet ? 'bg-blue-500 hover:bg-blue-600' : 'bg-gray-50 hover:bg-gray-100' }} 
           relative inline-flex items-center space-x-2 px-4 py-4 border text-sm font-medium rounded-md focus:outline-none focus:ring-1 focus:ring-indigo-500"
    wire:click="toggleMode"
>
    <span>{{ $isSet ? 'Set' : 'Add' }}</span>
</button>

Why This Approach is Superior

This Livewire methodology is superior because it adheres to the principles of component-based architecture. Instead of manipulating the DOM directly with raw JavaScript, we delegate the state management to the server. This ensures that your data integrity is maintained, and any changes are reflected consistently across the entire application, making development faster and less error-prone. For building complex, interactive features in Laravel, understanding how Livewire manages reactivity is crucial for mastering modern framework development, as seen in best practices documented by teams focusing on robust backend architecture like those at laravelcompany.com.

Conclusion

Achieving dynamic styling based on user interaction is easily accomplished when you embrace the power of state management. By using Laravel Livewire to hold the application state and conditional logic, we transform a simple front-end visual change into a robust, server-driven interaction. This pattern allows developers to focus on business logic while letting the framework handle the complex synchronization between the backend data and the dynamic presentation layer.