skip to content

In Laravel Blade, how does a layout component with {{ $slot }} differ from an @extends layout, and which suits a new app?

level: juniorimportance: must knowfreq 68%

answer

  1. composition versus inheritance
  2. <x-layout> wraps, {{ $slot }} receives
  3. @section fills, @yield prints
  4. child view renders before its layout
  5. extends layout sees child's variables

basics

~20 s

A layout component wraps the page: markup between <x-layout> tags lands in the component's {{ $slot }}. An @extends layout is inheritance: the child fills @section blocks that the layout prints with @yield. New apps usually choose components.

solid answer

~40 s

Blade offers two layout styles. A **layout component** is composition: `resources/views/components/layout.blade.php` prints `{{ $slot }}`, and a page wraps its markup in `<x-layout>...</x-layout>`, passing extra pieces such as a title through attributes or named slots. **Template inheritance** is the older style: the child starts with `@extends('layouts.app')`, fills `@section('content')`, and the layout prints it with `@yield('content')`. The Blade compiler moves `@extends` to the end of the compiled child, so the child runs first, stores its sections, then the layout renders and receives every variable the child had. A layout component only receives what you pass it, plus `View::share` data. The docs present components first and the Livewire starter kit ships component layouts, so I'd pick components for a new app. `@extends` is still fully supported, and it is common in older codebases.

code

html · 14 lines
html
<!-- resources/views/components/layout.blade.php -->
<html>
<head><title>{{ $title ?? 'University' }}</title></head>
<body>
    @include('partials.nav')
    <main>{{ $slot }}</main>
</body>
</html>

<!-- resources/views/courses/show.blade.php -->
<x-layout :title="$course->name">
    <h1>{{ $course->name }}</h1>
    <p>{{ $course->summary }}</p>
</x-layout>

go deeper

for a junior

Recall both shapes: <x-layout> with {{ $slot }}, and @extends with @section and @yield. Be ready to write either one from memory for a simple page.

for a middle

Explain the render order: the child runs first and stores sections, then the layout renders. Contrast that with the layout component, which receives only what you pass it.

for a senior

Argue the choice for a real codebase: explicit layout inputs, one component model, and when migrating a working @extends app is not worth the churn.

for a principal

Frame it as a team convention: one documented layout style for new pages, with the other tolerated in legacy areas, so reviewers and newcomers learn a single model.

## Two ways to give a Blade page its shell Almost every page of a web application shares the same outer HTML: the `<head>`, the navigation, the footer. **Blade**, Laravel's template engine, gives you two ways to write that shell once and reuse it: - a **layout component**, which the page *wraps itself in* (composition); - a **layout view with template inheritance**, which the page *extends* (`@extends`, `@section`, `@yield`). Both ship in Laravel 13 and neither is deprecated. The Blade documentation presents components first and describes inheritance as "the primary way of building applications prior to the introduction of components". ## Layout components: composition A layout component is an ordinary Blade component, usually an **anonymous** one stored at `resources/views/components/layout.blade.php`. Its template prints `{{ $slot }}` where the page body belongs: 1. The layout file holds the full HTML document and prints `{{ $slot }}` inside `<body>`. 2. A page wraps its markup in `<x-layout> ... </x-layout>`. 3. Blade captures everything between the tags into the **default slot**, then renders the layout with that slot. Extra regions, such as a page title, travel as component attributes or named slots, and the layout prints them with a fallback such as `{{ $title ?? 'University' }}`. The current Livewire starter kit takes this route: its pages open with `<x-layouts::app :title="...">`. ## Template inheritance: @extends, @section, @yield With inheritance the layout is a plain view, for example `resources/views/layouts/app.blade.php`, containing `@yield('content')` placeholders. The child view: - declares its parent with `@extends('layouts.app')`; - fills named regions with `@section('content') ... @endsection` or the one-line form `@section('title', $course->name)`; - lets the layout print each region with `@yield('name')`, which may take a default as its second argument. The mechanism is worth knowing. The Blade compiler does not print anything where `@extends` appears. It adds a line to the **footer** of the compiled child that calls the view factory's `make()` for the layout, passing the child's `get_defined_vars()`, and renders it. So the child's code runs **first**, stores its sections in the shared view factory, and only then does the layout render and pull those sections back out. ## How the two styles differ | Aspect | Layout component | `@extends` layout | |---|---|---| | Model | composition: page wraps itself in the layout | inheritance: page fills holes in the layout | | Where content goes | `{{ $slot }}` plus named slots | `@yield('name')` for each `@section` | | Data the layout sees | only attributes, slots and `View::share` data | every variable the child view had | | Default for a missing region | `{{ $title ?? '...' }}` or a prop default | `@yield('title', 'Default')` | | Nesting | a section layout wraps itself in `<x-layout>` | a middle layout itself uses `@extends` | | Typical in | Laravel's own docs and the Livewire starter kit | older codebases and many tutorials | The **data-scope** row matters most in practice. An `@extends` layout silently receives every variable the child had, so a layout can come to depend on a variable only some controllers pass. A component layout only receives what it is explicitly given, which keeps its inputs visible at the call site. ## Which to pick For a new Laravel 13 app, prefer **layout components**: - the page reads top to bottom as HTML, with the shell visible as a tag; - the layout's inputs are declared rather than inherited from whatever the child defined; - it is the same mechanism as every other component, so there is one model to learn; - the official Blade starting points already use it. Choose `@extends` when you maintain an app already built on it, or when you want many independent named regions filled from deep inside a child. Rewriting working inheritance layouts purely for style is rarely worth it. ## Mixing them The two styles can live in the same application, even on the same page: a page can `@extends` a layout whose markup uses components, and a component layout can include partials. Stacks (`@push` and `@stack`) work with both, because in both cases the page's own content executes before the layout's markup is printed. ## Mistakes interviewers listen for - Claiming `@extends` is deprecated. It is documented and supported in Laravel 13; it is simply no longer the first style the docs show. - Expecting a layout component to see the page's variables. It does not; pass them as attributes, or share them deliberately. - Believing the layout renders first. With `@extends` the child runs first; with a component the slot is captured first. That order is what makes sections and stacks work. - Mixing the vocabularies: `@section('content')` inside `<x-layout>` does nothing useful, because a component layout never calls `@yield('content')`. - Putting request-specific data, such as the signed-in student's name, into the layout by querying inside it. A layout that runs queries on every page hides cost; supply that data from outside the template instead.

  • Why can an @extends layout print a variable the controller passed only to the child view, while a layout component cannot?
    The compiler turns `@extends` into a footer call to the view factory's `make()` for the layout, passing the child's `get_defined_vars()`, so the layout inherits the child's whole scope. A component's view is rendered with its own data only: its attributes, props and slots, plus anything registered with `View::share`. To use `$course` in a component layout you pass it, for example `<x-layout :course="$course">`.
  • How do you nest layouts, say a department section inside the site shell, in each style?
    With inheritance, the middle layout itself starts with `@extends('layouts.app')`, fills `@section('content')`, and yields its own inner section, such as `@yield('department-content')`, for pages to fill. With components, a `department-layout` component simply wraps its `{{ $slot }}` in `<x-layout>`, and pages use `<x-department-layout>`. Composition nests without any extra directives.

saying these in an interview costs you the question

  • @extends is deprecated in Laravel 13 and will be removed
  • A layout component automatically sees every variable the controller passed to the page
  • The layout renders first and the child's sections are fetched lazily afterwards
  • An application must use one layout style everywhere; the two cannot coexist
  • {{ $slot }} in a component and @yield('content') compile to the same thing