Styling Your Editor
ProseKit provides a headless editor framework that gives you complete control over your editor’s appearance. This guide will walk you through the various ways to style your ProseKit editor.
Basic Styles
ProseKit requires some basic styles to function properly. Import prosekit/basic/style.css
in your project to include these styles.
// Import the basic styles (required)
import 'prosekit/basic/style.css'
Typography Styles
ProseKit provides an optional set of typography styles that make your editor content look polished with minimal effort.
prosekit/basic/typography.css
provides a beautiful set of default styles for headings, paragraphs, lists, and other elements:
// Import both basic and typography styles
import 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'
Here’s what the default typography looks like:
import 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'
import { useMemo } from 'preact/hooks'
import { defineBasicExtension } from 'prosekit/basic'
import { createEditor } from 'prosekit/core'
import { ProseKit } from 'prosekit/preact'
import { typographyContent } from './typography-content'
export default function Editor() {
const editor = useMemo(() => {
return createEditor({ extension: defineBasicExtension(), defaultContent: typographyContent })
}, [])
return (
<ProseKit editor={editor}>
<div className='box-border h-full w-full min-h-36 overflow-y-hidden overflow-x-hidden rounded-md border border-solid border-gray-200 shadow dark:border-zinc-700 flex flex-col bg-white dark:bg-gray-950'>
<div className='relative w-full flex-1 box-border overflow-y-scroll'>
<div ref={editor.mount} className='ProseMirror box-border min-h-full px-[max(4rem,_calc(50%-20rem))] py-8 outline-none outline-0 [&_span[data-mention="user"]]:text-blue-500 [&_span[data-mention="tag"]]:text-violet-500'></div>
</div>
</div>
</ProseKit>
)
}
export const typographyContent = `
<h1>ProseKit Typography</h1>
<p>This example shows the typography styles provided by <code>prosekit/basic/typography.css</code>.</p>
<h2>Inline marks</h2>
<p>Text can be formatted in different ways: <strong>bold text</strong>, <em>italic text</em>, <u>underlined text</u>, <s>strikethrough text</s>, <code>inline code</code> and <a href="https://example.com">links</a>.</p>
<h2>Lists</h2>
<p>Here are different types of lists:</p>
<ul>
<li>Unordered list item 1</li>
<li>Unordered list item 2
<ul>
<li>Nested item A</li>
<li>Nested item B</li>
</ul>
</li>
</ul>
<ol>
<li>First ordered item</li>
<li>Second ordered item</li>
</ol>
<ul>
<li><input type="checkbox" checked />Completed task</li>
<li><input type="checkbox" />Pending task</li>
</ul>
<h2>Blockquotes</h2>
<blockquote>
<p>This is a blockquote demonstrating how quoted content appears in the editor. It can span multiple lines and maintains proper formatting.</p>
</blockquote>
<h2>Code Blocks</h2>
<pre><code>function example() {
const greeting = 'Hello ProseKit!';
console.log(greeting);
return greeting;
}</code></pre>
<h2>Horizontal Rule</h2>
<hr />
<h2>Images</h2>
<img src="https://picsum.photos/600/300" alt="Sample image" />
<h2>Tables</h2>
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
<tr>
<td>Cell 3</td>
<td>Cell 4</td>
</tr>
</tbody>
</table>
`
import 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'
import { defineBasicExtension } from 'prosekit/basic'
import { createEditor } from 'prosekit/core'
import { ProseKit } from 'prosekit/solid'
import { typographyContent } from './typography-content'
export default function Editor() {
const editor = createEditor({ extension: defineBasicExtension(), defaultContent: typographyContent })
return (
<ProseKit editor={editor}>
<div class='box-border h-full w-full min-h-36 overflow-y-hidden overflow-x-hidden rounded-md border border-solid border-gray-200 shadow dark:border-zinc-700 flex flex-col bg-white dark:bg-gray-950'>
<div class='relative w-full flex-1 box-border overflow-y-scroll'>
<div ref={editor.mount} class='ProseMirror box-border min-h-full px-[max(4rem,_calc(50%-20rem))] py-8 outline-none outline-0 [&_span[data-mention="user"]]:text-blue-500 [&_span[data-mention="tag"]]:text-violet-500'></div>
</div>
</div>
</ProseKit>
)
}
export const typographyContent = `
<h1>ProseKit Typography</h1>
<p>This example shows the typography styles provided by <code>prosekit/basic/typography.css</code>.</p>
<h2>Inline marks</h2>
<p>Text can be formatted in different ways: <strong>bold text</strong>, <em>italic text</em>, <u>underlined text</u>, <s>strikethrough text</s>, <code>inline code</code> and <a href="https://example.com">links</a>.</p>
<h2>Lists</h2>
<p>Here are different types of lists:</p>
<ul>
<li>Unordered list item 1</li>
<li>Unordered list item 2
<ul>
<li>Nested item A</li>
<li>Nested item B</li>
</ul>
</li>
</ul>
<ol>
<li>First ordered item</li>
<li>Second ordered item</li>
</ol>
<ul>
<li><input type="checkbox" checked />Completed task</li>
<li><input type="checkbox" />Pending task</li>
</ul>
<h2>Blockquotes</h2>
<blockquote>
<p>This is a blockquote demonstrating how quoted content appears in the editor. It can span multiple lines and maintains proper formatting.</p>
</blockquote>
<h2>Code Blocks</h2>
<pre><code>function example() {
const greeting = 'Hello ProseKit!';
console.log(greeting);
return greeting;
}</code></pre>
<h2>Horizontal Rule</h2>
<hr />
<h2>Images</h2>
<img src="https://picsum.photos/600/300" alt="Sample image" />
<h2>Tables</h2>
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
<tr>
<td>Cell 3</td>
<td>Cell 4</td>
</tr>
</tbody>
</table>
`
<script lang="ts">
import 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'
import { defineBasicExtension } from 'prosekit/basic'
import { createEditor } from 'prosekit/core'
import { ProseKit } from 'prosekit/svelte'
import { typographyContent } from './typography-content'
const editor = createEditor({ extension: defineBasicExtension(), defaultContent: typographyContent })
const mount = (element: HTMLElement) => {
editor.mount(element)
return { destroy: () => editor.unmount() }
}
</script>
<ProseKit {editor}>
<div class='box-border h-full w-full min-h-36 overflow-y-hidden overflow-x-hidden rounded-md border border-solid border-gray-200 shadow dark:border-zinc-700 flex flex-col bg-white dark:bg-gray-950'>
<div class='relative w-full flex-1 box-border overflow-y-scroll'>
<div use:mount class='ProseMirror box-border min-h-full px-[max(4rem,_calc(50%-20rem))] py-8 outline-none outline-0 [&_span[data-mention="user"]]:text-blue-500 [&_span[data-mention="tag"]]:text-violet-500'></div>
</div>
</div>
</ProseKit>
export const typographyContent = `
<h1>ProseKit Typography</h1>
<p>This example shows the typography styles provided by <code>prosekit/basic/typography.css</code>.</p>
<h2>Inline marks</h2>
<p>Text can be formatted in different ways: <strong>bold text</strong>, <em>italic text</em>, <u>underlined text</u>, <s>strikethrough text</s>, <code>inline code</code> and <a href="https://example.com">links</a>.</p>
<h2>Lists</h2>
<p>Here are different types of lists:</p>
<ul>
<li>Unordered list item 1</li>
<li>Unordered list item 2
<ul>
<li>Nested item A</li>
<li>Nested item B</li>
</ul>
</li>
</ul>
<ol>
<li>First ordered item</li>
<li>Second ordered item</li>
</ol>
<ul>
<li><input type="checkbox" checked />Completed task</li>
<li><input type="checkbox" />Pending task</li>
</ul>
<h2>Blockquotes</h2>
<blockquote>
<p>This is a blockquote demonstrating how quoted content appears in the editor. It can span multiple lines and maintains proper formatting.</p>
</blockquote>
<h2>Code Blocks</h2>
<pre><code>function example() {
const greeting = 'Hello ProseKit!';
console.log(greeting);
return greeting;
}</code></pre>
<h2>Horizontal Rule</h2>
<hr />
<h2>Images</h2>
<img src="https://picsum.photos/600/300" alt="Sample image" />
<h2>Tables</h2>
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
<tr>
<td>Cell 3</td>
<td>Cell 4</td>
</tr>
</tbody>
</table>
`
<script setup lang="ts">
import 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'
import { defineBasicExtension } from 'prosekit/basic'
import { createEditor } from 'prosekit/core'
import { ProseKit } from 'prosekit/vue'
import {
ref,
watchPostEffect,
} from 'vue'
import { typographyContent } from './typography-content'
const editor = createEditor({
extension: defineBasicExtension(),
defaultContent: typographyContent,
})
const editorRef = ref<HTMLDivElement | null>(null)
watchPostEffect((onCleanup) => {
editor.mount(editorRef.value)
onCleanup(() => editor.unmount())
})
</script>
<template>
<ProseKit :editor="editor">
<div class='box-border h-full w-full min-h-36 overflow-y-hidden overflow-x-hidden rounded-md border border-solid border-gray-200 shadow dark:border-zinc-700 flex flex-col bg-white dark:bg-gray-950'>
<Toolbar />
<div class='relative w-full flex-1 box-border overflow-y-scroll'>
<div ref="editorRef" class='ProseMirror box-border min-h-full px-[max(4rem,_calc(50%-20rem))] py-8 outline-none outline-0 [&_span[data-mention="user"]]:text-blue-500 [&_span[data-mention="tag"]]:text-violet-500' />
</div>
</div>
</ProseKit>
</template>
export const typographyContent = `
<h1>ProseKit Typography</h1>
<p>This example shows the typography styles provided by <code>prosekit/basic/typography.css</code>.</p>
<h2>Inline marks</h2>
<p>Text can be formatted in different ways: <strong>bold text</strong>, <em>italic text</em>, <u>underlined text</u>, <s>strikethrough text</s>, <code>inline code</code> and <a href="https://example.com">links</a>.</p>
<h2>Lists</h2>
<p>Here are different types of lists:</p>
<ul>
<li>Unordered list item 1</li>
<li>Unordered list item 2
<ul>
<li>Nested item A</li>
<li>Nested item B</li>
</ul>
</li>
</ul>
<ol>
<li>First ordered item</li>
<li>Second ordered item</li>
</ol>
<ul>
<li><input type="checkbox" checked />Completed task</li>
<li><input type="checkbox" />Pending task</li>
</ul>
<h2>Blockquotes</h2>
<blockquote>
<p>This is a blockquote demonstrating how quoted content appears in the editor. It can span multiple lines and maintains proper formatting.</p>
</blockquote>
<h2>Code Blocks</h2>
<pre><code>function example() {
const greeting = 'Hello ProseKit!';
console.log(greeting);
return greeting;
}</code></pre>
<h2>Horizontal Rule</h2>
<hr />
<h2>Images</h2>
<img src="https://picsum.photos/600/300" alt="Sample image" />
<h2>Tables</h2>
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
<tr>
<td>Cell 3</td>
<td>Cell 4</td>
</tr>
</tbody>
</table>
`
Styling with Tailwind CSS
ProseKit works well with Tailwind CSS for styling your editor. For pre-built editor components that use Tailwind CSS, see the Components documentation.