Skip to content
0phoff edited this page Nov 17, 2023 · 4 revisions

Slots in Vue and Slidev

Slots are a powerful concept in Vue that allows you to place HTML content in different spots of a vue component.

Component Usage Result
<template>
  <header>
    <slot name="header" />
  </header>
  <main>
    <slot />
  </main>
  <footer>
    <slot name="footer" />
  </footer>
</template>
                                  
                                  
<Component>
  <template #header>
    <h1>My Website</h1>
  </template>
  
  <template #default>
    <div>content</div>
  </template>

  <template #footer>
    <div>john.doe@webdev.com</div>
  </template>
</Component>
<header>
  <h1>My Website</h1>
</header>
<main>
  <div>content</div>
</main>
<footer>
  <div>john.doe@webdev.com</div>
</footer>
                                  
                                  
                                  
                                  

These slots are also usable in slidev with the ::slot-name:: syntax and are very useful to provide more advanced layouts.

Component Usage
<template>
  <header>
    <slot name="header" />
  </header>
  <main>
    <slot />
  </main>
  <footer>
    <slot name="footer" />
  </footer>
</template>
                                  
                                  
::header::
 
# Slide Heading
 
::default::
 
This will be in the main content.
 
::footer::
 
This is the footer
 
---

Slots in the Eavise theme

Many layouts defined in this theme use slots to be able to modify different parts of the slide. While most of them are straightforward, the ::content:: slot in the default layout might be less intuitive. The reason for its existence is that the default layout caters to two different usage scenarios.

Roughly speaking, the default layout is constructed as follows:

<div class="slidev-layout flex flex-col">
  <div class="slot-default">
    <slot />
  </div>
  <div class="slot-content flex-grow">
    <slot name="slot-content" />
  </div>
</div>

The first use case is to enter your content in the ::default:: slot, where each element will be laid out as a regular web page would. If your first element is a title, it will be styled in a banner and we add some margin between this title and the next element. Additionally, all elements except the title get a left-margin so that your content does not stick to the side of your slide.

However, more often than not you want to lay out the content of your slide differently. Maybe you want to center the content vertically, use multiple columns or even arrange all the items in a grid. In that case these default margins are annoying and ideally you want a container around the content that takes up all of the vertical whitespace in the slide. This is exactly what you get when you use the ::content:: slot. By adding a flex-grow, the wrapper around the content will effectively grow to take up all remaining space of the slide, allowing you to more easily organize your content. Because this slot is meant for more advanced placement, it does not provide any default styling of its children whatsoever. In order to style the div that contains your content you can either pass classes to the content-class argument of the layout or you can style the div directly with the :deep(.slot-content) selector.

slidev-eavise-scenario1

slidev-eavise-scenario2

Example slide without using the ::content:: slot. Note the automatic margins.

Example slide with ::content:: slot. The red markings come from chrome devtools and show how flexbox nicely centers the paragraph.

Code
# Scenario 1
This slide is created without `::content::` slot and thus all of its elements are laid out as a regular web page.
Do note the left-margin that is added to all elements, as well as the space between the title and this first paragraph.

- Lists get a margin as well!
- 2
- 3

---
content-class: flex flex-col justify-center
---

# Scenario 2
::content::

This paragraph is inside of the `::content::` slot, which we styled so that the paragraph gets centered inside of the available whitespace.
Note that there is no margin applied by default anymore.

---

HINT
While providing your own styling of .slot-content is fine, you can also take a look at the various predefined styles in order to get a head start. The example given for scenario 2 is actually the implementation of the Stack Layout.