Markdown Syntax
Slides are written within a single markdown file (by default ./slides.md
).
You can use the Markdown features as you normally would, with the additional support of inlined HTML and Vue Components. Styling using UnoCSS is also supported. Use ---
padded with a new line to separate your slides.
# Slidev
Hello, World!
---
# Page 2
Directly use code blocks for highlighting
```ts
console.log('Hello, World!')
```
---
# Page 3
You can directly use UnoCSS CSS and Vue components to style and enrich your slides.
<div class="p-3">
<Tweet id="20" />
</div>
Frontmatter & Layouts
Specify layouts and other metadata for each slide by converting the separators into frontmatter blocks. Each frontmatter starts with a triple-dash and ends with another. Texts between them are data objects in YAML format. For example:
---
layout: cover
---
# Slidev
This is the cover page.
---
layout: center
background: /background-1.png
class: 'text-white'
---
# Page 2
This is a page with the layout `center` and a background image.
---
# Page 3
This is a default page without any additional metadata.
Refer to customization for more details.
Prettier Support
Available since v0.44
The custom syntax might not be compatible with some formatters like Prettier. You can either install the Prettier Plugin or use a direct yaml
code block to define the frontmatter instead:
---
layout: cover
---
# Slidev
This is the cover page.
---
```yaml
# The first yaml block will be treated as the frontmatter of that slide
layout: center
background: /background-1.png
class: 'text-white'
```
# Page 2
This is a page with the layout `center` and a background image.
Code Blocks
One big reason that led to the creation of Slidev was the need to perfectly display code in slides. Consequently, you can use Markdown-flavored code blocks to highlight your code.
```ts
console.log('Hello, World!')
```
Slidev has Shiki built in as the syntax highlighter. Refer to the highlighters section for more details.
Line Highlighting
To highlight specific lines, simply add line numbers within brackets {}
. Line numbers start counting from 1 by default.
```ts {2,3}
function add(
a: Ref<number> | number,
b: Ref<number> | number
) {
return computed(() => unref(a) + unref(b))
}
```
To change what's highlighted with multiple clicks, you can use |
to separate each stage:
```ts {2-3|5|all}
function add(
a: Ref<number> | number,
b: Ref<number> | number
) {
return computed(() => unref(a) + unref(b))
}
```
This will first highlight a: Ref<number> | number
and b: Ref<number> | number
, and then return computed(() => unref(a) + unref(b))
after one click, and lastly, the whole block.
You can set the line number to hide
to hide the code block or none
to not highlight any line:
```ts {hide|none}
function add(
a: Ref<number> | number,
b: Ref<number> | number
) {
return computed(() => unref(a) + unref(b))
}
```
TIP
Learn more in the click animations guide.
Line Numbers
You can enable line numbering for all slides by setting lineNumbers: true
in the global config or enable each code block individually by setting lines: true
. You can also set the starting line for each code block and highlight the lines accordingly; it defaults to 1:
```ts {6,7}{lines:true,startLine:5}
function add(
a: Ref<number> | number,
b: Ref<number> | number
) {
return computed(() => unref(a) + unref(b))
}
```
Max Height
If the code doesn't fit into one slide, you use the maxHeight
to set a fixed height and enable scrolling:
```ts {2|3|7|12}{maxHeight:'100px'}
function add(
a: Ref<number> | number,
b: Ref<number> | number
) {
return computed(() => unref(a) + unref(b))
}
/// ...as many lines as you want
const c = add(1, 2)
```
TwoSlash Integration
Available since v0.46
This feature is only available when you set highlighter
to shiki
TwoSlash is a powerful tool for rendering TypeScript code blocks with type information on hover or inlined. It's quite useful for preparing slides for JavaScript/TypeScript-related topics.
To use it, you can add twoslash
to the code block's language identifier:
```ts twoslash
import { ref } from 'vue'
const count = ref(0)
// ^?
```
It will be rendered as:
import { ref } from 'vue'
const count = ref(0)
Shiki Magic Move
Available since v0.48
Shiki Magic Move enables you to have a granular transition between code changes, similar to Keynote's Magic Move. You can check the playground to see how it works.
In Slidev, we bind the magic-move to the clicks system. The syntax is to wrap multiple code blocks representing each step with ````md magic-move
(mind it's 4 backticks), this will be transformed into one code block, that morphs to each step as you click.
````md magic-move
```js
console.log(`Step ${1}`)
```
```js
console.log(`Step ${1 + 1}`)
```
```ts
console.log(`Step ${3}` as string)
```
````
It's also possible to mix Magic Move with line highlighting and line numbers, for example:
````md magic-move {at:4, lines: true}
```js {*|1|2-5}
let count = 1
function add() {
count++
}
```
Non-code blocks in between as ignored, you can put some comments.
```js {*}{lines: false}
let count = 1
const add = () => count += 1
```
````
Monaco Editor
Whenever you want to do some modification in the presentation, simply add {monaco}
after the language id — it turns the block into a fully-featured Monaco editor!
```ts {monaco}
console.log('HelloWorld')
```
Learn more about configuring Monaco.
Monaco Diff Editor
Monaco can also generate a diff between two code blocks. Use {monaco-diff}
to turn the block into a Monaco diff editor and use ~~~
to separate the original and modified code!
```ts {monaco-diff}
console.log('Original text')
~~~
console.log('Modified text')
```
Monaco Runner
Available since v0.48
Slidev also provides the Monaco Runner Editor, which allows you to run the code directly in the editor and see the result. Use {monaco-run}
to turn the block into a Monaco Runner Editor.
```ts {monaco-run}
function distance(x: number, y: number) {
return Math.sqrt(x ** 2 + y ** 2)
}
console.log(distance(3, 4))
```
It provides the editor with a "Run" button, and shows the result of the code execution right below the code block. You may also modify the code and the result will be re-evaluated on the fly.
By default it will automatically run the code when the slide is loaded; if you want to instead explicitly trigger the run, you can set {autorun:false}
.
```ts {monaco-run} {autorun:false}
console.log('Click the play button to run me')
```
If you want to only show the output in certain clicks, you can use the showOutputAt
prop. The value is the same as v-click
.
```ts {monaco-run} {showOutputAt:'+1'}
console.log('Shown after 1 click')
```
Currently Slidev supports running JavaScript and TypeScript code out-of-box. Refer to Custom Code Runners for custom languages support.
Writable Monaco Editor
Available since v0.49.5
You can also use the Import Code Snippets syntax combining with the {monaco-write}
directive, to link your Monaco Editor with a file on your filesystem. This will allow you to edit the code directly in the editor and save the changes back to the file.
<<< ./some-file.ts {monaco-write}
When using this, be sure to back up your files beforehand, as the changes will be saved directly to the file.
Embedded Styles
You can use <style>
tag in your Markdown directly to override styles for the current slide.
# This is Red
<style>
h1 {
color: red;
}
</style>
---
# Next slide is not affected
The <style>
tag in Markdown is always scoped. As a result, a selector with a child combinator (.a > .b
) is unusable as such; see the previous link. To have global style overrides, check out the customization section.
Powered by UnoCSS, you can directly use nested css and directives (e.g. --uno:
or @apply
)
# Slidev
> Hello `world`
<style>
blockquote {
code {
--uno: text-teal-500 dark:text-teal-400;
}
}
</style>
Static Assets
Just like you would do in markdown, you can use images pointing to a remote or local URL.
For remote assets, the built-in vite-plugin-remote-assets
will cache them onto the disk at first run, ensuring instant loading even for large images later on.
![Remote Image](https://sli.dev/favicon.png)
For local assets, put them into the public
folder and reference them with a leading slash (i.e., /pic.png
, NOT ./pic.png
, which is relative to the working file).
![Local Image](/pic.png)
If you want to apply custom sizes or styles, you can convert them to the <img>
tag:
<img src="/pic.png" class="m-40 h-40 rounded shadow" />
Notes
You can also create presenter notes for each slide. They will show up in Presenter Mode for you to reference during presentations.
In Markdown, the last comment block in each slide will be treated as a note.
---
layout: cover
---
# Page 1
This is the cover page.
<!-- This is a note -->
---
# Page 2
<!-- This is NOT a note because it precedes the content of the slide -->
The second page
<!--
This is another note
-->
Basic Markdown and HTML are also supported in notes when the Presenter renders note content.
Click Markers
Available since v0.48
For some slides you might have longer notes that could be hard to find your place. Slidev supports click markers that allow highlighting and auto-scrolling to the section of notes from your corresponding content. Put [click]
markers at the beginning of any line in your notes for the timing you need to go to another click. You may skip n
clicks by using [click:{n+1}]
. For example:
<!--
Content before the first click
[click] This will be highlighted after the first click
Also highlighted after the first click
- [click] This list element will be highlighted after the second click
[click:3] Last click (skip two clicks)
-->
Slidev divides the content between the click markers and highlights it in presenter notes, synchronized with your slide progress.
Icons
Slidev allows you to have access to virtually all open-source icon sets directly in your markdown after installing the corresponding package. Powered by unplugin-icons
and Iconify.
The naming follows Iconify's convention of {collection-name}-{icon-name}
. For example:
<mdi-account-circle />
- from Material Design Icons -@iconify-json/mdi
<carbon-badge />
- from Carbon -@iconify-json/carbon
<uim-rocket />
- from Unicons Monochrome -@iconify-json/uim
<twemoji-cat-with-tears-of-joy />
- from Twemoji -@iconify-json/twemoji
<logos-vue />
- from SVG Logos -@iconify-json/logos
- And much more...
Browse and search for all the icons available with Icônes.
Styling Icons
You can style the icons just like other HTML elements. For example:
<uim-rocket />
<uim-rocket class="text-3xl text-red-400 mx-2" />
<uim-rocket class="text-3xl text-orange-400 animate-ping" />
Slots
Available since v0.18
Some layouts can provide multiple contributing points using Vue's named slots.
For example, in two-cols
layout, you can have two columns left (default
slot) and right (right
slot) side by side.
---
layout: two-cols
---
<template v-slot:default>
# Left
This shows on the left
</template>
<template v-slot:right>
# Right
This shows on the right
</template>
Left
This shows on the left
Right
This shows on the right
We also provide a shorthand syntactical sugar ::name::
for slot name. The following works exactly the same as the previous example.
---
layout: two-cols
---
# Left
This shows on the left
::right::
# Right
This shows on the right
You can also explicitly specify the default slot and provide in the custom order.
---
layout: two-cols
---
::right::
# Right
This shows on the right
::default::
# Left
This shows on the left
Import Code Snippets
Available since v0.47.0
You can import code snippets from existing files via the following syntax:
<<< @/snippets/snippet.js
TIP
The value of @
corresponds to your package's root directory. It's recommended to put snippets in @/snippets
, for compatibility with the Monaco editor. Alternatively, you can also import from relative paths.
You can also use a VS Code region to only include the corresponding part of the code file:
<<< @/snippets/snippet.js#region-name
To explicitly specify the language of the imported code, you can add a language identifier after:
<<< @/snippets/snippet.js ts
Any code block features like line highlighting and Monaco editor are also supported:
<<< @/snippets/snippet.js {2,3|5}{lines:true}
<<< @/snippets/snippet.js ts {monaco}{height:200px}
Configurations
All configurations can be defined in the Markdown file. For example:
---
theme: seriph
layout: cover
background: 'https://source.unsplash.com/1600x900/?nature,water'
---
# Slidev
This is the cover page.
Learn more about frontmatter configurations.
LaTeX
Slidev comes with LaTeX support out-of-box, powered by KaTeX.
Inline
Surround your LaTeX with a single $
on each side for inline rendering.
$\sqrt{3x-1}+(1+x)^2$
Block
Use two ($$
) for block rendering. This mode uses bigger symbols and centers the result.
$$
\begin{array}{c}
\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} &
= \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\
\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
\nabla \cdot \vec{\mathbf{B}} & = 0
\end{array}
$$
Learn more: Demo | KaTeX | markdown-it-katex
LaTex line highlighting
Available since v0.43.1
To highlight specific lines, simply add line numbers within bracket {}
. Line numbers start counting from 1 by default.
$$ {1|3|all}
\begin{array}{c}
\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} &
= \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\
\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
\nabla \cdot \vec{\mathbf{B}} & = 0
\end{array}
$$
The at
and finally
options of code blocks are also available for LaTeX blocks.
Chemical equations
To enable the rendering of chemical equations, the mhchem KaTeX extension needs to be loaded.
Create vite.config.ts
with the following content:
import 'katex/contrib/mhchem'
export default {}
Now chemical equations can be rendered properly.
$$
\displaystyle{\ce{B(OH)3 + H2O <--> B(OH)4^- + H+}}
$$
Learn more: Syntax
Diagrams
You can also create diagrams / graphs from textual descriptions in your Markdown, powered by Mermaid.
Code blocks marked as mermaid
will be converted to diagrams, for example:
```mermaid
sequenceDiagram
Alice->John: Hello John, how are you?
Note over Alice,John: A typical interaction
```
You can further pass an options object to it to specify the scaling and theming. The syntax of the object is a JavaScript object literal, you will need to add quotes ('
) for strings and use comma (,
) between keys.
```mermaid {theme: 'neutral', scale: 0.8}
graph TD
B[Text] --> C{Decision}
C -->|One| D[Result 1]
C -->|Two| E[Result 2]
```
Multiple Entries
Available since v0.15
You can split your slides.md
into multiple files and organize them however you'd like.
slides.md
:
# Page 1
This is a normal page
---
src: ./subpage2.md
---
<!-- this page will be loaded from './subpage2.md' -->
Inline content will be ignored
subpage2.md
:
# Page 2
This page is from another file
Frontmatter Merging
You can provide frontmatter instructions from both your main entry and external markdown pages. If there are duplicate keys in them, the ones from the main entry have the higher priority. For example:
slides.md
:
---
src: ./cover.md
background: https://sli.dev/bar.png
class: text-center
---
cover.md
:
---
layout: cover
background: https://sli.dev/foo.png
---
# Cover
Cover Page
They will end up being equivalent to the following page:
---
layout: cover
background: https://sli.dev/bar.png
class: text-center
---
# Cover
Cover Page
Page Reuse
With the multi-entries support, reusing pages could be straightforward. For example:
---
src: ./cover.md
---
---
src: ./intro.md
---
---
src: ./content.md
---
---
# reuse
src: ./content.md
---
MDC Syntax
Available since v0.43.0
Slidev supports optional MDC (Markdown Components) Syntax powered by markdown-it-mdc
.
You can enable it by adding mdc: true
to the frontmatter of your markdown file.
---
mdc: true
---
This is a [red text]{style="color:red"} :inline-component{prop="value"}
![](/image.png){width=500px lazy}
::block-component{prop="value"}
The **default** slot
::
Learn more about MDC Syntax.