Skip to main content

Styling the Editor

Tiptap is designed to be unstyled by default, giving you complete control over the appearance of your editor. However, it does include some minimal base styles to ensure proper functionality.

Base Styles

Tiptap automatically injects minimal CSS styles required for the editor to function properly. These styles are injected by default but can be disabled.
.ProseMirror {
  position: relative;
  word-wrap: break-word;
  white-space: pre-wrap;
  white-space: break-spaces;
  -webkit-font-variant-ligatures: none;
  font-variant-ligatures: none;
  font-feature-settings: "liga" 0;
}

.ProseMirror [contenteditable="false"] {
  white-space: normal;
}

.ProseMirror [contenteditable="false"] [contenteditable="true"] {
  white-space: pre-wrap;
}

.ProseMirror pre {
  white-space: pre-wrap;
}

.ProseMirror:focus {
  outline: none;
}
Source: packages/core/src/style.ts:1

Disabling CSS Injection

You can disable automatic CSS injection and provide your own styles.
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'

const editor = new Editor({
  element: document.querySelector('.editor'),
  extensions: [StarterKit],
  injectCSS: false, // Disable automatic CSS injection
})
Source: packages/core/src/Editor.ts:88

Editor Container Styling

Style the editor container to customize its appearance.
/* Basic editor styling */
.tiptap {
  padding: 1rem;
  min-height: 200px;
  border: 1px solid #e2e8f0;
  border-radius: 0.5rem;
  background: white;
}

/* Focus state */
.tiptap:focus {
  outline: none;
  border-color: #6366f1;
  box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
}

/* Caret color */
.tiptap {
  caret-color: #6366f1;
}
Source: demos/src/Examples/Default/React/styles.scss:55

Content Styling

Style the content inside the editor.
/* Headings */
.tiptap h1 {
  font-size: 2rem;
  font-weight: 700;
  line-height: 1.2;
  margin: 1.5rem 0 1rem;
}

.tiptap h2 {
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1.3;
  margin: 1.25rem 0 0.75rem;
}

.tiptap h3 {
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.4;
  margin: 1rem 0 0.5rem;
}

/* Paragraphs */
.tiptap p {
  margin: 0.75rem 0;
  line-height: 1.6;
}

/* Lists */
.tiptap ul,
.tiptap ol {
  padding-left: 1.5rem;
  margin: 0.75rem 0;
}

.tiptap li {
  margin: 0.25rem 0;
}

/* Blockquotes */
.tiptap blockquote {
  border-left: 4px solid #e2e8f0;
  padding-left: 1rem;
  margin: 1rem 0;
  color: #64748b;
  font-style: italic;
}

/* Code */
.tiptap code {
  background: #f1f5f9;
  border-radius: 0.25rem;
  padding: 0.125rem 0.25rem;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.875em;
  color: #e11d48;
}

.tiptap pre {
  background: #1e293b;
  color: #e2e8f0;
  border-radius: 0.5rem;
  padding: 1rem;
  margin: 1rem 0;
  overflow-x: auto;
}

.tiptap pre code {
  background: none;
  color: inherit;
  font-size: 0.875rem;
  padding: 0;
}

/* Marks */
.tiptap strong {
  font-weight: 700;
}

.tiptap em {
  font-style: italic;
}

.tiptap mark {
  background: #fef08a;
  padding: 0.125rem 0;
  border-radius: 0.125rem;
}

.tiptap a {
  color: #6366f1;
  text-decoration: underline;
  cursor: pointer;
}

.tiptap a:hover {
  color: #4f46e5;
}

Placeholder Styling

Style placeholder text for empty content.
/* Using the Placeholder extension */
.tiptap p.is-editor-empty:first-child::before {
  content: attr(data-placeholder);
  float: left;
  color: #adb5bd;
  pointer-events: none;
  height: 0;
}

/* Alternative approach */
.tiptap.is-empty::before {
  content: 'Write something...';
  color: #adb5bd;
  position: absolute;
  pointer-events: none;
}

Selection Styling

Customize text selection appearance.
.tiptap ::selection {
  background: rgba(99, 102, 241, 0.2);
}

.tiptap::-moz-selection {
  background: rgba(99, 102, 241, 0.2);
}

Gap Cursor Styling

The gap cursor appears between block nodes.
.ProseMirror-gapcursor {
  display: none;
  pointer-events: none;
  position: absolute;
  margin: 0;
}

.ProseMirror-gapcursor:after {
  content: "";
  display: block;
  position: absolute;
  top: -2px;
  width: 20px;
  border-top: 1px solid #6366f1;
  animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite;
}

@keyframes ProseMirror-cursor-blink {
  to {
    visibility: hidden;
  }
}

.ProseMirror-focused .ProseMirror-gapcursor {
  display: block;
}
Source: packages/core/src/style.ts:34

Dark Mode

Implement dark mode for your editor.
/* Dark mode container */
.dark .tiptap {
  background: #1e293b;
  border-color: #334155;
  color: #e2e8f0;
}

.dark .tiptap:focus {
  border-color: #6366f1;
  box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
}

/* Dark mode content */
.dark .tiptap h1,
.dark .tiptap h2,
.dark .tiptap h3 {
  color: #f1f5f9;
}

.dark .tiptap code {
  background: #334155;
  color: #fb7185;
}

.dark .tiptap pre {
  background: #0f172a;
}

.dark .tiptap blockquote {
  border-left-color: #475569;
  color: #94a3b8;
}

.dark .tiptap mark {
  background: #854d0e;
  color: #fef08a;
}

.dark .tiptap a {
  color: #818cf8;
}

.dark .tiptap a:hover {
  color: #a5b4fc;
}

CSS Variables

Use CSS variables for consistent theming.
:root {
  /* Colors */
  --editor-bg: #ffffff;
  --editor-text: #1e293b;
  --editor-border: #e2e8f0;
  --editor-focus: #6366f1;
  --editor-placeholder: #94a3b8;
  
  /* Spacing */
  --editor-padding: 1rem;
  --editor-border-radius: 0.5rem;
  
  /* Typography */
  --editor-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --editor-font-size: 1rem;
  --editor-line-height: 1.6;
}

.dark {
  --editor-bg: #1e293b;
  --editor-text: #e2e8f0;
  --editor-border: #334155;
  --editor-focus: #6366f1;
  --editor-placeholder: #64748b;
}

.tiptap {
  background: var(--editor-bg);
  color: var(--editor-text);
  border: 1px solid var(--editor-border);
  border-radius: var(--editor-border-radius);
  padding: var(--editor-padding);
  font-family: var(--editor-font-family);
  font-size: var(--editor-font-size);
  line-height: var(--editor-line-height);
}

.tiptap:focus {
  border-color: var(--editor-focus);
}
Source: demos/src/Examples/Default/React/styles.scss:1

Typography with Tailwind

Use Tailwind’s typography plugin for beautiful defaults.
<template>
  <EditorContent 
    :editor="editor" 
    class="prose prose-lg max-w-none focus:outline-none"
  />
</template>

Custom Node Styling

Add custom classes to specific node types.
import { Node } from '@tiptap/core'

export const Paragraph = Node.create({
  name: 'paragraph',
  
  addOptions() {
    return {
      HTMLAttributes: {
        class: 'my-paragraph',
      },
    }
  },
})

Responsive Design

Make your editor responsive.
/* Mobile */
@media (max-width: 640px) {
  .tiptap {
    padding: 0.75rem;
    font-size: 0.9375rem;
  }
  
  .tiptap h1 {
    font-size: 1.5rem;
  }
  
  .tiptap h2 {
    font-size: 1.25rem;
  }
}

/* Tablet */
@media (min-width: 641px) and (max-width: 1024px) {
  .tiptap {
    padding: 1rem;
  }
}

/* Desktop */
@media (min-width: 1025px) {
  .tiptap {
    padding: 1.5rem;
    max-width: 65ch;
    margin: 0 auto;
  }
}
Optimize editor content for printing.
@media print {
  .tiptap {
    border: none;
    padding: 0;
  }
  
  .tiptap a {
    text-decoration: underline;
    color: #000;
  }
  
  .tiptap a[href]:after {
    content: " (" attr(href) ")";
  }
  
  .tiptap pre,
  .tiptap blockquote {
    page-break-inside: avoid;
  }
}

Scrollbar Styling

Customize scrollbar appearance.
.tiptap::-webkit-scrollbar {
  width: 14px;
  height: 14px;
}

.tiptap::-webkit-scrollbar-track {
  background-clip: padding-box;
  background-color: transparent;
  border: 4px solid transparent;
  border-radius: 8px;
}

.tiptap::-webkit-scrollbar-thumb {
  background-clip: padding-box;
  background-color: rgba(0, 0, 0, 0);
  border: 4px solid rgba(0, 0, 0, 0);
  border-radius: 8px;
}

.tiptap:hover::-webkit-scrollbar-thumb {
  background-color: rgba(0, 0, 0, 0.1);
}

.tiptap::-webkit-scrollbar-thumb:hover {
  background-color: rgba(0, 0, 0, 0.15);
}
Source: demos/preview/style.css:101
Remember that Tiptap is headless, so you have complete control over styling. The examples above are just starting points.

Next Steps

TypeScript

Add type safety to your editor

Collaborative Editing

Enable real-time collaboration