Overview
The MarkdownRenderer class provides functionality for rendering Markdown content to HTML elements. It extends MarkdownRenderChild and implements MarkdownPreviewEvents and HoverParent interfaces.
Available since version 0.9.7
Properties
app
Reference to the app instance.
hoverPopover
The hover popover associated with this renderer, if any.
The hover popover or null
file
The file being rendered (abstract getter).
Static Methods
render()
Renders Markdown string to an HTML element.
A reference to the app object
The Markdown source code to render
The element to append the rendered content to
The normalized path of the Markdown file, used to resolve relative internal links
A parent component to manage the lifecycle of the rendered child components
A promise that resolves when rendering is complete
// Basic usage
const container = document.createElement('div');
await MarkdownRenderer.render(
this.app,
'# Hello World\n\nThis is **bold** text.',
container,
'',
this
);
// Add to DOM
containerEl.appendChild(container);
renderMarkdown() (Deprecated)
Renders Markdown string to an HTML element.
This method is deprecated. Use MarkdownRenderer.render() instead.
The normalized path of the Markdown file
A parent component to manage lifecycle
Available since version 0.10.6
// Deprecated - use render() instead
await MarkdownRenderer.renderMarkdown(
'# Title',
container,
'',
this
);
Examples
Rendering Markdown in a Modal
import { Modal, MarkdownRenderer } from 'obsidian';
class MarkdownModal extends Modal {
markdown: string;
constructor(app: App, markdown: string) {
super(app);
this.markdown = markdown;
}
onOpen() {
const { contentEl } = this;
// Render the markdown
MarkdownRenderer.render(
this.app,
this.markdown,
contentEl,
'',
this
);
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
}
// Usage
const modal = new MarkdownModal(
this.app,
'# Preview\n\nThis is rendered **Markdown**.'
);
modal.open();
Rendering with Source Path for Link Resolution
const activeFile = this.app.workspace.getActiveFile();
if (activeFile) {
const container = containerEl.createDiv();
const markdown = `
See [[Other Note]] for more details.

`.trim();
// Links will be resolved relative to the active file's path
await MarkdownRenderer.render(
this.app,
markdown,
container,
activeFile.path,
this
);
}
Rendering File Content
const file = this.app.vault.getAbstractFileByPath('Notes/Example.md');
if (file instanceof TFile) {
const content = await this.app.vault.read(file);
const container = containerEl.createDiv();
await MarkdownRenderer.render(
this.app,
content,
container,
file.path,
this
);
}
Rendering in a Custom View
import { ItemView, MarkdownRenderer } from 'obsidian';
class CustomView extends ItemView {
getViewType(): string {
return 'custom-view';
}
getDisplayText(): string {
return 'Custom View';
}
async onOpen() {
const container = this.containerEl.children[1];
container.empty();
const markdown = `
# Custom View Content
This view renders **dynamic** Markdown content.
- Item 1
- Item 2
- Item 3
`.trim();
await MarkdownRenderer.render(
this.app,
markdown,
container,
'',
this
);
}
}
Rendering with Component Lifecycle Management
import { Component, MarkdownRenderer } from 'obsidian';
class MarkdownComponent extends Component {
containerEl: HTMLElement;
markdown: string;
constructor(containerEl: HTMLElement, markdown: string) {
super();
this.containerEl = containerEl;
this.markdown = markdown;
}
async onload() {
// Render on load
await MarkdownRenderer.render(
this.app,
this.markdown,
this.containerEl,
'',
this
);
}
onunload() {
// Clean up on unload
this.containerEl.empty();
}
}
// Usage
const component = new MarkdownComponent(
containerEl,
'# Dynamic Content'
);
component.load();
// Later, when done:
component.unload();
Rendering Markdown from Frontmatter
const file = this.app.workspace.getActiveFile();
if (file) {
const cache = this.app.metadataCache.getFileCache(file);
const description = cache?.frontmatter?.description;
if (description && typeof description === 'string') {
const container = containerEl.createDiv();
await MarkdownRenderer.render(
this.app,
description,
container,
file.path,
this
);
}
}
Rendering with Custom Styling
const container = containerEl.createDiv({
cls: 'custom-markdown-container'
});
const markdown = `
# Styled Content
This content will be rendered with custom styling.
`;
await MarkdownRenderer.render(
this.app,
markdown,
container,
'',
this
);
// Add custom CSS
container.style.padding = '1em';
container.style.border = '1px solid var(--background-modifier-border)';
container.style.borderRadius = '4px';
Rendering Multiple Sections
const sections = [
'# Section 1\n\nFirst section content.',
'# Section 2\n\nSecond section content.',
'# Section 3\n\nThird section content.'
];
for (const section of sections) {
const sectionContainer = containerEl.createDiv({
cls: 'markdown-section'
});
await MarkdownRenderer.render(
this.app,
section,
sectionContainer,
'',
this
);
}
Dynamic Content Updates
class DynamicMarkdownRenderer extends Component {
containerEl: HTMLElement;
currentContent: string;
constructor(containerEl: HTMLElement) {
super();
this.containerEl = containerEl;
this.currentContent = '';
}
async updateContent(markdown: string) {
// Clear previous content
this.containerEl.empty();
// Render new content
await MarkdownRenderer.render(
this.app,
markdown,
this.containerEl,
'',
this
);
this.currentContent = markdown;
}
}
// Usage
const renderer = new DynamicMarkdownRenderer(containerEl);
await renderer.updateContent('# Initial Content');
// Later, update with new content
await renderer.updateContent('# Updated Content\n\nNew text here.');
MarkdownRenderChild
Base class that MarkdownRenderer extends.
class MarkdownRenderChild extends Component {
containerEl: HTMLElement;
constructor(containerEl: HTMLElement);
}
Tips
Always provide a Component instance to manage the lifecycle of rendered content. This ensures proper cleanup when the content is no longer needed.
Use the sourcePath parameter to ensure internal links and embedded images resolve correctly relative to the source file.
The render method is asynchronous. Always await it to ensure the content is fully rendered before interacting with the DOM.