Laravel Blade Components and Slots: A Comprehensive Guide
15 May 2025 | Category: Laravel
Blade components and slots are powerful features in Laravel’s templating engine, enabling developers to create reusable, modular, and maintainable UI elements. Components encapsulate HTML, CSS, and logic, while slots provide flexibility for injecting dynamic content into those components. This SEO-friendly, plagiarism-free guide explains Blade components and slots, how to create and use them, and best practices. Based on Laravel 11 (as of May 2025), this tutorial is designed for beginners and intermediate developers.
What are Blade Components and Slots?
Blade Components
A Blade component is a reusable piece of UI (e.g., a button, modal, or alert) defined as a class and a corresponding Blade template. Components combine logic and presentation, making it easy to reuse complex UI elements across your application.
Slots
Slots are placeholders within a component’s template that allow you to inject custom content when using the component. They provide flexibility, enabling components to adapt to different contexts while maintaining a consistent structure.
Key Benefits
- Reusability: Define UI elements once and use them anywhere.
- Modularity: Keep templates organized and maintainable.
- Flexibility: Slots allow customization of component content.
- Consistency: Ensure uniform design and behavior across views.
- Encapsulation: Combine logic and markup in a single unit.
Creating a Blade Component
Laravel provides Artisan commands to generate components, or you can create them manually. Components consist of:
- Class: Handles logic and data (in
app/View/Components/
). - Template: Defines the markup (in
resources/views/components/
).
Step 1: Generate a Component
Run the Artisan command to create a component:
php artisan make:component Alert
This generates:
- Class:
app/View/Components/Alert.php
- Template:
resources/views/components/alert.blade.php
Step 2: Define the Component
Component Class (Alert.php
):
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class Alert extends Component
{
public $type;
public $dismissible;
public function __construct($type = 'info', $dismissible = false)
{
$this->type = $type;
$this->dismissible = $dismissible;
}
public function render()
{
return view('components.alert');
}
}
- Properties:
$type
and$dismissible
are passed as attributes. - render(): Points to the component’s Blade template.
Component Template (alert.blade.php
):
<div class="alert alert-{{ $type }} {{ $dismissible ? 'alert-dismissible' : '' }}" role="alert">
{{ $slot }}
@if($dismissible)
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
@endif
</div>
- $slot: Placeholder for content passed between the component’s tags.
- Dynamic Classes: Uses
$type
and$dismissible
for styling.
Step 3: Use the Component
Use the component in a Blade view with the x-
prefix:
<x-alert type="success" :dismissible="true">
Operation completed successfully!
</x-alert>
- type=”success”: Sets the alert style (e.g., green for success).
- :dismissible=”true”: Enables the close button (uses
:
for PHP expressions). - Content: “Operation completed successfully!” is passed to
$slot
.
Output (assuming Bootstrap CSS):
<div class="alert alert-success alert-dismissible" role="alert">
Operation completed successfully!
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
Working with Slots
Slots allow you to inject custom content into specific parts of a component’s template. Components can have a default slot (unnamed) and named slots for more complex structures.
Default Slot
The default slot ($slot
) captures content passed between the component’s opening and closing tags.
Example Template (modal.blade.php
):
<div class="modal fade" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
{{ $slot }}
</div>
</div>
</div>
Usage:
<x-modal>
<div class="modal-header">
<h5>Modal Title</h5>
</div>
<div class="modal-body">
<p>Modal content goes here.</p>
</div>
</x-modal>
- The header and body are injected into
$slot
.
Named Slots
Named slots allow you to define multiple placeholders for specific content.
Component Template (card.blade.php
):
<div class="card">
<div class="card-header">
{{ $header }}
</div>
<div class="card-body">
{{ $slot }}
</div>
<div class="card-footer">
{{ $footer }}
</div>
</div>
Usage:
<x-card>
<x-slot name="header">
<h5>Card Title</h5>
</x-slot>
<p>This is the card body content.</p>
<x-slot name="footer">
<button>Save</button>
</x-slot>
</x-card>
<x-slot name="header">
: Assigns content to the$header
slot.- Default content (
<p>
) goes to$slot
. <x-slot name="footer">
: Assigns content to the$footer
slot.
Shorthand Syntax:
<x-card>
@slot('header')
<h5>Card Title</h5>
@endslot
<p>Card body content.</p>
@slot('footer')
<button>Save</button>
@endslot
</x-card>
Conditional Slots
Check if a slot has content using @isset
:
<div class="card">
@isset($header)
<div class="card-header">{{ $header }}</div>
@endisset
<div class="card-body">{{ $slot }}</div>
</div>
- The header is only rendered if the
$header
slot is provided.
Passing Data to Components
Components can accept data via attributes, constructor parameters, or slots.
Via Attributes
Pass data as HTML attributes:
<x-alert type="danger" :dismissible="true">
Error occurred!
</x-alert>
type="danger"
: Static value.:dismissible="true"
: Dynamic PHP expression.
Via Constructor
The component class constructor defines accepted parameters:
public function __construct($type = 'info', $dismissible = false)
{
$this->type = $type;
$this->dismissible = $dismissible;
}
Via Slots
Pass structured content through slots, as shown in the named slots example.
Accessing Attributes in Templates
All attributes are available in the template via $attributes
:
<div {{ $attributes->merge(['class' => 'alert alert-' . $type]) }}>
{{ $slot }}
</div>
$attributes->merge()
: Combines passed attributes with defaults.
Anonymous Components
Anonymous components are simpler, consisting only of a Blade template without a class. They’re ideal for purely presentational elements.
Create an Anonymous Component
Create a file in resources/views/components/
(e.g., button.blade.php
):
<button {{ $attributes->merge(['class' => 'btn btn-' . ($type ?? 'primary')]) }}>
{{ $slot }}
</button>
Use the Component
<x-button type="success">
Click Me
</x-button>
- No class is needed; the template handles everything.
- Attributes like
type
are accessed directly.
Advanced Component Features
Component Aliases
Register a shorter alias for components in app/Providers/AppServiceProvider.php
:
public function boot()
{
Blade::component('components.alert', 'alert-box');
}
Use as:
<x-alert-box type="info">Message</x-alert-box>
Dynamic Components
Render components dynamically:
@php
$componentName = 'alert';
@endphp
<x-dynamic-component :component="$componentName" type="warning">
Warning message!
</x-dynamic-component>
Component Methods
Add methods to the component class for logic:
public function isDismissible()
{
return $this->dismissible;
}
Use in the template:
@if($component->isDismissible())
<button class="btn-close"></button>
@endif
Inline Components
Define a component in a single file without a separate template:
public function render()
{
return <<<'blade'
<div class="alert alert-{{ $type }}">
{{ $slot }}
</div>
blade;
}
Best Practices for Blade Components and Slots
- Use Components for Reusability: Encapsulate repeated UI elements (e.g., buttons, modals).
- Leverage Slots: Use named slots for flexible, complex components.
- Keep Components Focused: Each component should have a single responsibility.
- Use Anonymous Components for Simplicity: Opt for anonymous components for lightweight UI.
- Secure Output: Rely on
{{ }}
for escaped output; use{!! !!}
cautiously. - Merge Attributes: Use
$attributes->merge()
to combine classes or attributes. - Organize Components: Group related components in subdirectories (e.g.,
resources/views/components/forms/
). - Test Components: Write tests for component logic in
tests/
.
Example: Real-World Component
Modal Component (modal.blade.php
):
<div class="modal fade" id="{{ $id }}" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
{{ $header }}
</div>
<div class="modal-body">
{{ $slot }}
</div>
<div class="modal-footer">
{{ $footer }}
</div>
</div>
</div>
</div>
Class (Modal.php
):
namespace App\View\Components;
use Illuminate\View\Component;
class Modal extends Component
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
public function render()
{
return view('components.modal');
}
}
Usage:
<x-modal id="confirmModal">
<x-slot name="header">
<h5>Confirm Action</h5>
</x-slot>
<p>Are you sure you want to proceed?</p>
<x-slot name="footer">
<button class="btn btn-primary" data-bs-dismiss="modal">Cancel</button>
<button class="btn btn-danger">Confirm</button>
</x-slot>
</x-modal>
Conclusion
Blade components and slots are essential for building modular, reusable, and maintainable views in Laravel. Components encapsulate UI logic and markup, while slots provide flexibility for injecting custom content. By using class-based or anonymous components, leveraging named slots, and following best practices, you can create clean, consistent, and scalable front-end code.
Next Steps:
- Create a component:
php artisan make:component Alert
. - Experiment with named slots in a complex component like a modal.
- Explore Laravel’s official documentation for advanced component features.
For further learning, engage with the Laravel community on platforms like X or dive into the official Laravel documentation. Start building reusable UI with Blade components today!