Custom Components
Replace default HTML elements with custom Svelte components for enhanced functionality.
MDSX allows you to replace default HTML elements like <h1>
, <p>
, and <a>
with your own custom Svelte components.
You might use custom components to:
- Apply consistent brand styling to headings and paragraphs.
- Automatically add
target="_blank"
to external links. - Replace standard
<img>
tags with an advanced image component that handles lazy loading and placeholders.
How It Works
Custom components are provided through Blueprints.
When you export a component from a blueprint file with a name that matches an HTML tag (e.g., h1
, p
, a
), MDSX automatically uses your component for all corresponding tags in any markdown file that uses that blueprint.
These components are exported from the <script module>
block of a blueprint file.
Creating a Custom Component
A custom component is just a standard Svelte component. It receives the original element's content as the children
prop, which is a Svelte 5 Snippet.
Here's an example of a custom component for an <h1>
element:
<script lang="ts">
import type { Snippet } from 'svelte';
let { children }: { children: Snippet } = $props();
</script>
<h1 class="mb-6 border-b-2 border-gray-200 pb-2 text-4xl font-bold text-gray-900">
{@render children()}
</h1>
Using a Custom Component
To use this component, you export it from a blueprint with the corresponding tag name.
<script lang="ts" context="module">
export { default as h1 } from '$lib/components/h1.svelte';
</script>
<script lang="ts">
import type { Snippet } from 'svelte';
let { children }: { children: Snippet } = $props();
</script>
<article class="prose">
{@render children()}
</article>
Now, whenever a markdown file using this blueprint contains an <h1>
, it will be rendered with your h1.svelte
component.
Example: Custom Anchor Tag
Let's create a custom <a>
component that automatically adds target="_blank"
and an icon to external links.
The Component
The component checks if the href
is an external URL and conditionally adds target="_blank"
and an icon.
<script lang="ts">
import type { HTMLAnchorAttributes } from 'svelte/elements';
let { href, children, ...restProps }: HTMLAnchorAttributes = $props();
const isExternal = $derived(!href.startsWith('/'));
const target = $derived(isExternal ? '_blank' : undefined);
</script>
<a {href} {target} class="text-blue-600 hover:text-blue-800" {...restProps}>
{@render children?.()}
{#if isExternal}
<svg class="ml-1 inline h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
/>
</svg>
{/if}
</a>
The Blueprint
Export the new component from your blueprint.
<script lang="ts" module>
export { default as a } from '$lib/components/a.svelte';
</script>
<!-- ... -->
Usage
Now, all links in your markdown will use this component.
An external link to [Svelte](https://svelte.dev).
An internal link to our [Getting Started](/docs/getting-started) guide.
The first link will open in a new tab with the icon, while the second will be a standard navigation link.
Supported Elements
You can override any standard HTML element tag. Common use cases include:
h1
,h2
,h3
,h4
,h5
,h6
p
a
ul
,ol
,li
blockquote
code
,pre
img
hr
table
,thead
,tbody
,tr
,th
,td
Note
When you provide a custom component for pre
, it will wrap code blocks. If you provide a code
component, it will apply to both inline code
and the <code>
element inside a <pre>
block.