How to Use Slots in Vue.js

Luke Chinworth
Solid Digital
Published in
2 min readJul 23, 2018

If you haven’t used slots in Vue.js, the docs offer a great explanation and overview, but if you’ve ever written html, you’ve already kinda used slots.

You’ve probably done something like this a million times:

<div id="hero">
<h1 id="hero-title">Hero title</h1>
</div>

Now let’s say instead of the plain div you want to use a vue component, fancy-hero let’s call it, because it adds some nice presentation or functionality.

<fancy-hero animation="slideInLeft">
<h1 id="hero-title">Hero title</h1>
</fancy-hero>

And the fancy-hero component definition (using vue’s single-file-component notation) might look something like this:

<template>
<div id="hero" :class="fancyClassesComputedFromAnimationProp"></div>
</template>

The problem is this fancy-hero template does not declare where the content passed to the component (the h1) should be rendered. Without a content outlet, vue will simply discard the content and not render it, resulting in this html:

<div id="hero" class="fancy animation classes from component"></div>

We got our sweet presentation, but our h1 is gone. To fix this we have to tell vue where to render the content we pass to fancy-hero. We do so with the special slot component provided by vue.

<template>
<div id=”hero” :class="fancyClassesComputedFromAnimationProp">
<slot></slot>
</div>
</template>

Now, all content passed to fancy-hero will be rendered where the slot is declared in its template. Now we get the desired html.

<div id="hero" class="fancy animation classes from component">
<h1 id="hero-title">Hero title</h1>
</div>

Just like html, you can pass as much or as little content as you want to a vue slot — it will render whatever you give it. For example, we could add a subtitle to our hero component just by passing the markup.

<fancy-hero animation="slideInLeft">
<h1 id="hero-title">Hero title</h1>
<small id="hero-subtitle">Hero Subtitle</small>
</fancy-hero>

Which renders as:

<div id="hero" class="fancy animation classes from component">
<h1 id="hero-title">Hero title</h1>
<small id="hero-subtitle">Hero Subtitle</small>
</div>

Furthermore, you can even pass other components:

<fancy-hero animation="slideInLeft">
<fancy-title>Hero title</fancy-title>
<fancy-subtitle>Hero Subtitle</fancy-subtitle>
</fancy-hero>

Hopefully this helped you understand how to use slots in Vue.js. If my explanation didn’t click with you, check out the Vue.js docs for an alternative explanation. If my explanation did click but you’re still not convinced slots are useful, be on the lookout for our follow up post on why you should use slots in Vue.js.

If you want to learn more now, check out the docs for all the advanced slot features not covered in this post.

--

--