Starters guide to Laravel templates, with Bootstrap

Starters guide to Laravel templates, with Bootstrap

·

7 min read

In this guide I will be guiding you through the basic concepts of defining a base layout in Laravel using Blade templates. I will share with you how I after years of working with Laravel choose to structure my layouts. We will be creating our example using Bootstrap, so you have something to continue with after, if you prefer other frameworks such as Tailwind, you should be able to do so, but already knowing the CSS framework would be beneficial then.

I will cover the basic use of Laravel Blade with Bootstrap for a signed in user, you should get the idea afterwards if you wish to create a layout for the landing page as well.

This article is written with Laravel 7 in mind.

Setup

After you setup your initial Laravel you should use Laravel/UI to install Bootstrap:

  1. Install Laravel/UI: composer require laravel/ui
  2. Prepare Bootstrap: php artisan ui bootstrap
  3. Install assets: npm install

Structure and core layout

Worth noting about Laravel Blade

Section names

You can only use a section name once in a structure, this means you are going to have a conflict if you 2 templates uses the same section name:

// Template 1
@yield('content')

// Template2
@extends('Template1')
@section('content')
  @yield('content')
@endsection

This is prone to errors !

Ending sections

A section can be ended by either @stop or @endsection. Which you choose is up to you, but in my opinion @endsection gives you a more readable template.

Structure

I like to keep my structure as closely related to the one suggested from Laravel, this ensures it's easier for me in the future to go back and modify the code, but also easier for participants to understand my code. Therefor all Blade templates are stored in /resources/views.

Layout specific templates will be put inside the subdirectory layout. Within that I like to keep a subfolder called parts, this contains menu, footer, header and other commonly used parts that should be accessible through the various layout templates.

Base

Within layout create a new file called base.blade.php. This is the base template for all templates – but only extended by layout templates.

<!DOCTYPE html>
<html lang="en">
    <head profile="http://www.w3.org/2005/10/profile">
        <meta charset="utf-8">
        <title>My site</title>
        <meta name="app-url" content="{{ url('/') }}">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link href="{{ url(mix('css/app.css')) }}" rel="stylesheet">
    </head>
    <body>
        @yield('page')
        <script src="{{ url(mix('js/app.js')) }}"></script>
    </body>
</html>

Blank

Next create a file in layout called blank.blade.php, this will be the most basic layout. It may seem redundant not just to extend base, but this way we can keep a streamlined architecture and sometimes you might want to force ie a footer to even the minimal layout.

@extends('layout.base')

@section('page')
    @yield('content')
@endsection

Also, we ensured the section you later refer to is always content.

App

For the signed in user the there should be a layout that represents the app view. This will include:

  • Navigation
  • Header
  • App content area
@extends('layout.base')

@section('page')
    @include('layout.parts.navbar')

    <div class="container-fluid">
        <div class="row h-100 mt-3">
            <div class="col">
                @yield('content')
            </div>
        </div>
    </div>
@endsection

@include and @yield

We have worked with 2 different ways to work with external template files. The difference is in logic, or direction you might say, they are injected. @include is when the template working in knows which external template to inject, such as navigation. This is useful when you have parts of templates that are used in many templates but don't want to rewrite it.

@yield is when the template working in, doesn't know the content, this should be more seen as a variable placeholder for child templates to inject content into the parent. (@section).

Not covered here, but useful to add is a global handler for alert and info messages.

For our navbar this should be stored in layouts.parts.navbar. As the navbar isn't going to have any sub-elements I will just use the default from Bootstrap:

<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">Navbar</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
      <a class="nav-item nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
      <a class="nav-item nav-link" href="#">Features</a>
    </div>
  </div>
</nav>

Using the layout

@extends

Now building our content page we can benefit from the layout templates. @extends allows to inherit a parent template sort of how extends works for a class in PHP. I like to put @extends at the top of my blade files.

Create the file /resources/views/content.blade.php with the following content:

@extends('layouts.app')

@section

Remember we used @yield in the layouts file? This is referred to as sections in child templates. This means we create a section in the child, which is injected at the yield point in the parent template.

You should avoid ending up with 2 names that are the same, unless it's unlikely the templates are used together such as for the different layouts

Make your content site look like this:

@extends('layouts.app')

@section('content')
    <div class="row">
        <div class="col">
             <div class="card">
                 <div class="card-body">
                     My content goes here, both plain text, HTML and Blade syntax.
                 </div>
             </div>
        </div>
    </div>
@endsection