Laravel @stack @push @append in Blade 
                                      Templates

Laravel @stack @push @append in Blade Templates

A 'stack' can easily be defined as a collection of items. In Laravel, a stack's main purpose is to facilitate the pushing of different styles, scripts and segments from different places to a layout that is being extended. Let's try and break that down, shall we....

The traditional way to avoid clustering too much code on blade files while using Laravel is to use sections; One page acts as the template, and this page is usually the app.blade.php file located in the view/layouts folder. The function @yield('content') is used on the master page to explicitly define a section in a layout while the child page contains an @section('content') to inject content layout from the blade template it is extending. The contents of the sections will be displayed using the @yield('content') directive.

In English, @yield() creates a sort of vacuum where @section() contents are put.

Master Blade File

<!DOCTYPE html>
<html>
<head>
    <title>Example File Html</title>
</head>
<body>
    <div id="app"> 
         <main class="">

               /**The yield directive**/     
               @yield('content')

         </main>
    </div>
</body>
</html>

Child Blade File

@extends('layouts.app')

@section('content')
     /**Main content of the child page**/   
     <div class="container"...>
@endsection

The catch with using the @yield() and @section() directives is that it can only be rendered once on the browser; what I mean is that if a situation arises, in which you are trying to display more than one section on a blade file, the second section overrides the first and only the last one gets displayed. This was illustrated perfectly by a user on StackOverflow with this answer. Notice how when the loop runs, the push directive gets displayed once while the section directive gets displayed once.

Enter @stack directive...

The @stack directive makes it possible for a user to push multiple styles and scripts to child layouts without having to necessarily hardcode them on the master layout file. Take for example a website's index which contains font awesome icons and an adjacent page that has a summernote javascript plugin and styles. It would be inefficient if the index page were to load both the font awesome and summernote scripts. This happens most times because of the index page. being a child layout usually extends a master blade file that loads all styles and scripts to all pages, regardless of the necessity.

Below is an example of how a workaround to this can be achieved using the @push() and @stack() directive.

Master Blade File

This file acts as the main template which will be extended

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    //GLOBAL styles 
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">


    //to define the title for pages
    <title>@yield('title')</title>

    <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
//End of GLOBAL styles

    //Will be used to load unique page styles for each individual page
    @stack('styles')

</head>
<body>

    <div id="app">
        @yield('app')
    </div>

       //Will be used to load unique page styles for each individual page
       @stack('scripts')

</body>
</html>

Child Blade File

Extends the Master Blade file

//Extend the Master layout
@extends('layouts.master')


//Using prepend so that these GLOBAL styles can get loaded first before all the other things in a stack
@prepend('styles')
    @vite(['resources/sass/app.scss', 'resources/css/app.css'])
@endprepend


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


//Using prepend so that these GLOBAL scripts can get loaded first before all the other things in a stack
@prepend('scripts')
    @vite(['resources/js/app.js'])
@endprepend

Partials Blade Files

//Partial content that clutters up the child pages if not removed

//partials.main.php file
<main class="py-4">
    @yield('content')
</main>

//partials.main.php file contains the navigation bar code

Now notice the different styles and scripts used in the following two pages

Index Page

Page that contains page specific styles and the font awesome scripts

@extends('layouts.app')

@section('title', 'Push & Stack')

//Page specific styles only applicable on this page
@push('styles')

 //Font awesome link
    <link rel="stylesheet"  href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">

    <style>
        .new_page_link {
            text-decoration: none;
            color: gray;
            border-bottom: 1px solid gray;
        }

        .new_page_link:hover {
            color: red;
            border-bottom: 1px solid red;
        }

        .fontawesome_div {
            font-size: large;
            font-family: 'Times New Roman';
        }

        .fontawesome_icon_name {
            font-size: medium;
        }

        .div_title {
            color: grey;
            font-family: 'Times New Roman';
        }
    </style>
@endpush

@section('content')

@endsection

//Page specific scripts only applicable on this page
@push('scripts')

@endpush

Other Page

Page that contains summernote plugin and page specific styles

@extends('layouts.app')

//Insert Title of choice for the current page
@section('title', 'Other Styles Page')


//Page specific styles only applicable on this page
@push('styles')

    //Summernote CSS - CDN Link 
    <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-lite.min.css" rel="stylesheet">
    <!-- //Summernote CSS - CDN Link -->

    <style>
        .heading {
            font-family: Jokerman;
        }

        .new_page_link {
            text-decoration: none;
            color: red;
            border-bottom: 1px solid red;
        }
        .new_page_link:hover {
            color: darkslategray;
            border-bottom: 1px solid darkslategray;
        }
    </style>
@endpush

@section('content')

@endsection

//Page specific scripts only applicable on this page
@push('scripts')

     //Summernote JS - CDN Link
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-lite.min.js"></script>

    //Summernote script
    <script>
        $(document).ready(function() {
            $("#your_summernote").summernote();
            $('.dropdown-toggle').dropdown();
        });
    </script>
@endpush

Outcome [Index Page]

Outcome[Other Page]

...and that is how you can utilize the @blade() and @stack directives to push indipendent styles and scripts to different pages without hardcoding them to the master file template.

The files for this demo can be accesed via my Github