Custom Vue Components
VueMarkik allows you to customize how markdown elements are rendered by providing your own Vue components. This gives you complete control over the styling and behavior of any HTML element in your rendered markdown.
There are two approaches to customize markdown rendering:
- Using the
componentsprop - Pass custom Vue components defined in separate files - Using Vue template slots - Define custom rendering inline with template slots
Both approaches give you full control over styling and behavior. Choose based on whether you want to reuse components across multiple places (use components prop) or keep customization inline (use slots).
Precedence
If you define both a custom component (via components prop) and a slot for the same HTML element, the slot will take precedence. This allows you to override component-level customizations on a per-instance basis.
Using Custom Vue Components
The components prop accepts an object mapping HTML element names to Vue components. This is ideal when you want to reuse the same custom styling across multiple markdown instances.
Example: Custom H1 Component
First, create a Vue component for your custom element:
<template>
<h1 class="custom-heading">
<slot />
</h1>
</template>
<style scoped>
.custom-heading {
color: #42b883;
font-weight: bold;
border-bottom: 3px solid #35495e;
padding-bottom: 0.5rem;
}
</style>TIP
The <slot /> element is required to render the child nodes (text content, nested elements, etc.) of the markdown element. Without it, your custom component would be empty.
Then use it by passing it to the components prop:
<template>
<Markdown :text="markdown" :components="components" />
</template>
<script setup lang="ts">
import { Markdown } from 'vuemarkik';
import CustomH1 from './CustomH1.vue';
const components = {
h1: CustomH1,
};
const markdown = `\
# Custom Heading
This heading will be rendered using CustomH1 component.
`;
</script>Live Demo:
Custom Heading
This heading will be rendered using CustomH1 component.
Example: Custom Code Component
You can customize any HTML element, including inline code:
<template>
<code class="custom-code">
<slot />
</code>
</template>
<style scoped>
.custom-code {
background-color: #f3f4f6;
color: #e74c3c;
padding: 0.2rem 0.4rem;
border-radius: 4px;
font-family: 'Monaco', 'Courier New', monospace;
font-weight: bold;
}
</style>Use it the same way:
<script setup lang="ts">
import { Markdown } from 'vuemarkik';
import CustomCode from './CustomCode.vue';
const components = {
code: CustomCode,
};
const markdown = 'Here is some `inline code` that will be styled.';
</script>
<template>
<Markdown :text="markdown" :components="components" />
</template>Live Demo:
Here is some inline code that will be styled.
Using Vue Template Slots
Instead of creating separate component files, you can use Vue template slots to customize rendering inline. This approach uses the MarkdownChildNodes component to render the element's children.
Example: Custom H1 with Slots
<template>
<Markdown :text="markdown">
<template #h1="node">
<h1 class="custom-heading">
<MarkdownChildNodes :node="node" />
</h1>
</template>
</Markdown>
</template>
<script setup lang="ts">
import { Markdown, MarkdownChildNodes } from 'vuemarkik';
const markdown = `\
# Custom Heading
This heading is styled with an inline template slot.
`;
</script>
<style scoped>
.custom-heading {
color: #42b883;
font-weight: bold;
border-bottom: 3px solid #35495e;
padding-bottom: 0.5rem;
}
</style>The node parameter contains the element's data, including childMarkdown which holds the rendered children. The MarkdownChildNodes component renders these children for you.
Live Demo:
Custom Heading
This heading is styled with an inline template slot.
Example: Custom Code with Slots
<template>
<Markdown :text="markdown">
<template #code="node">
<code class="custom-code">
<MarkdownChildNodes :node="node" />
</code>
</template>
</Markdown>
</template>
<script setup lang="ts">
import { Markdown, MarkdownChildNodes } from 'vuemarkik';
const markdown = 'Here is some `inline code` with custom styling.';
</script>
<style scoped>
.custom-code {
background-color: #f3f4f6;
color: #e74c3c;
padding: 0.2rem 0.4rem;
border-radius: 4px;
font-family: 'Monaco', 'Courier New', monospace;
font-weight: bold;
}
</style>Live Demo:
Here is some inline code with custom styling.
Combining Both Approaches
You can mix both approaches - use the components prop for some elements and slots for others:
Precedence
If you define both a custom component (via components prop) and a slot for the same HTML element, the slot will take precedence. This allows you to override component-level customizations on a per-instance basis.
<template>
<Markdown :text="markdown" :components="{ h1: CustomH1 }">
<template #code="node">
<code class="inline-custom">
<MarkdownChildNodes :node="node" />
</code>
</template>
</Markdown>
</template>
<script setup lang="ts">
import { Markdown, MarkdownChildNodes } from 'vuemarkik';
import CustomH1 from './CustomH1.vue';
const markdown = `\
# Combined Approach
This uses a custom H1 component and has \`inline code\` with a slot.
## Subheading
More content to demonstrate.
`;
</script>
<style scoped>
.inline-custom {
background-color: #fef3c7;
color: #92400e;
padding: 0.2rem 0.5rem;
border-radius: 4px;
font-weight: 600;
border: 1px solid #fbbf24;
}
</style>Live Demo:
Combined Approach
This uses a custom H1 component and has inline code with a slot.
Subheading
More content to demonstrate.
