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:
- Install Laravel/UI:
composer require laravel/ui
- Prepare Bootstrap:
php artisan ui bootstrap
- 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.
Navbar
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