Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ivanhalen's avatar

Blade experts: use of @push and @stack for complex Laravel Blade layout

Working with Blade (Laravel template engine), I have two layouts:

  1. guest.blade.php, for guest related stuff (login, password request, etc.). Basically it's a slim template where content is centered (mostly forms)
  2. auth.blade.php, for authenticated users stuff (you know, the full layout with header, sidebar, etc.)

These two layouts have the following features (please sit down before having a headache :-) ):

  1. They share some common CSS and JS (bootstrap, font-awesome, jquery, etc.) in two different partials (css.blade.php in the document head and js.blade.php at the bottom).
  2. The auth.blade.php has obviously additional assets that aren't useful in slimmer guest.blade.php but are required in (mostly) ALL of the auth pages (select2, jquery-ui, etc.). Yes, I could put these additional CSS' and JS' in previously mentioned css.blade.php and js.blade.php and have them all in one file, but they would bloat guest.blade.php that I'd like to keep slim. And of course I don't want to put them in every child view! :-)
  3. Some views (both auth and guest related) could ask for peculiar assets just for that view: a dashboard could require some charts assets, a media manager could require multi-uploader assets, a login page could require a CSS or JS just for that login view.
  4. Last but not least, the order in which assets are loaded is important: i.e. for CSS
  • global_mandatory_styles (bootstrap, font-awesome, etc.)
  • global_mandatory_styles_addition (only for auth template)
  • page_levels_plugins (peculiar css plugin for the current view*)
  • theme_global_styles (mostly components)
  • page_level_styles (peculiar css custom styles for the current view**)
  • theme_layout_styles (the global styles and the "skin": blue, green, etc.)
  • my_custom_style

This order is what premium admin template Metronic 4.7.* comes with (I'll be using that), with the exclusion of "global_mandatory_styles_addition" and "my_custom_style" that I added on my own: I guess this loading order is mandatory.

Just to have an idea, take a look at these pages (each section I mentioned above has a START and END comment so you can easily locate; the same goes for JS but let's focus on CSS):

Summing, the goal is to keep one single css.blade.php for both guest.blade.php and auth.blade.php (1), add the shared auth assets when using the auth template (2), and being able to set custom assets per-view, equally when using guest and auth template (3) - and the same goes for javascript assets

* css plugins are mostly retrieved from cdn ** these are additional custom made styles only for that view, often an override of the cdn retrieved plugins

Oh, really I think I did, but don't know if it's the right approach since it seems a strange use of @push and @stack and I'd like to know if there's a cleaner solution

layouts.guest.blade.php

...
@include('partials.css')
...

layouts.auth.blade.php

@include('partials.stack') {{-- on top of the page --}}
...
@include('partials.css')
...

partials.css.blade.php

<!-- BEGIN GLOBAL MANDATORY STYLES -->
    <link href="cdn/bootstrap.css">
    <link href="cdn/font-awesome.css">
<!-- END GLOBAL MANDATORY STYLES -->

<!-- BEGIN GLOBAL MANDATORY STYLES, AUTH ONLY -->
    @stack('shared-auth')
<!-- END GLOBAL MANDATORY STYLES, AUTH ONLY -->

<!-- BEGIN PAGE LEVEL PLUGINS -->
    @stack('css-plugins')
<!-- END PAGE LEVEL PLUGINS -->

<!-- BEGIN THEME GLOBAL STYLES -->
    <link href="metronic/components.css">
    <link href="metronic/plugins.css">
<!-- END THEME GLOBAL STYLES -->

<!-- BEGIN PAGE LEVEL STYLES -->
    @stack('css-styles')
<!-- BEGIN PAGE LEVEL STYLES -->

<!-- BEGIN THEME LAYOUT STYLES, AUTH ONLY -->
    @stack('theme')
<!-- END THEME LAYOUT STYLES, AUTH ONLY -->

<!-- BEGIN MY STYLES -->
   <link href="custom/style.css">
<!-- BEGIN MY STYLES -->

partials.stack.blade.php (remember, this goes only on top of auth layout, so it contains the auth shared assets)

@push('shared-auth')
    <link href="cdn/jquery-ui.css">
    <link href="cdn/select2.css">
@endpush

@push('theme')
    <link href="metronic/darkblue.css">
@endpush

dashboard.blade.php

@push('css-plugins')
    <link href="cdn/morris.css">
    <link href="cdn/fullcalendar.css">
@endpush

@push('css-styles')
    <link ="metronic/morris-override.css">
@endpush

login.blade.php

@push('css-plugins')
    <link href="cdn/icheck-blue.css">
@endpush

@push('css-styles')
    <link href="metronic/login-style.css">
@endpush

Does it makes sense? The weird part to me is the @include('partials.stack') on top of layouts.auth.blade.php that pushes to the @stack of the other included file @include('partials.css')

It seems to me an uncommon (and undocumented, as far as I googled...) use of @push and @stack: are there better and recommended alternatives?

0 likes
8 replies
martinbean's avatar
Level 80

@ivanhalen I tend to have a “master” layout, that has the core HTML, and sets up sections and stacks for extending layouts to append to:

<!-- resources/views/layouts/master.blade.php -->
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta name="csrf-token" content="{{ csrf_token() }}" />
        @stack('meta')
        <title>@yield('title')</title>
        @stack('styles')
    </head>
    <body>
        <div id="app">
            @yield('app')
        </div>
        @stack('modals')
        @stack('scripts')
    </body>
</html>

I’ll then have an “app” layout that extends this, sets up the app section, and adds the base styles and scripts. This is the layout most views will use:

<!-- resources/views/layouts/app.blade.php -->
@extends('layouts.master')

@prepend('styles')
    <link href="{{ mix('css/app.css') }}" rel="stylesheet" />
@endprepend

@section('app)
    @include('partials.app.header')
    @include('partials.app.main')
    @include('partials.app.footer')
@endsection

@prepend('scripts')
    <script src="{{ mix('js/app.js') }}"></script>
@endprepend

Notice I use @prepend instead of @push. This ensures that these styles and scripts are first in that stack.

Using the app layout, you can then append any page-specific styles and scripts using @push as normal:

<!-- resources/views/home.blade.php -->
@extends('layouts.app')

@section('title', 'Home')

@push('styles')
    <link href="{{ mix('css/home.css') }}" rel="stylesheet" />
@endpush

@section('content')
    <div class="container">
        <p>Welcome to the home page.</p>
    </div>
@endsection

@push('scripts')
    <script src="{{ mix('js/home.js') }}"></script>
@endpush
4 likes
ivanhalen's avatar

Thanks @martinbean , this idea of having two nested layout templates would maybe point me in the right direction! :-) Just one thing: in the home.blade.php file there is a @section('content') but I don't see a corresponding @yield('content'): where do you usually put it?

martinbean's avatar

@ivanhalen It would be in the partials.app.main template:

<!-- resources/assets/views/partials/app/main.blade.php -->
<main class="site-main" role="main">
    <div class="site-content">
        @yield('content')
    </div>
</main>
ivanhalen's avatar

Thank, I did what you suggested and it seems much more leaner to me! :-)

Troj's avatar

Sorry for this useless comment, but i came across this post and i really want look into this method later on, @martinbean is explaining here. This is the only way to sort of bookmark it on this platform. I can follow the post, but there might never be any comment on this again.

PHPLaraDev's avatar

Thanks so much how to handle different css files dependent on the page using slots and components.

Moobbot21's avatar

Thanks a lot, it helps me to start learning Laravel better

Please or to participate in this conversation.