Tiptap placeholder missing: configure the hint and its CSS together

Tiptap's Placeholder extension adds decoration classes and a data-placeholder attribute; CSS makes the hint visible. If an empty editor has no hint, check both the extension configuration and the pseudo-element rule in the editor's actual document. A native placeholder attribute on the outer rich-text container does not replace that setup. Placeholder extension

For an original incident-handover editor, an empty heading should ask for the incident name, while an empty paragraph asks for the observed symptom. Those hints help the author begin. They must never become an incident name or symptom in the stored report.

Configure hints for the nodes authors fill in

In a current Tiptap 3 application with its base document extensions installed, add a configured Placeholder instance to the existing extension list:

import { Placeholder } from '@tiptap/extensions';

const handoverHints = Placeholder.configure({
  placeholder: ({ node }) => node.type.name === 'heading'
    ? 'Name the incident'
    : 'Describe the symptom you observed',
  showOnlyCurrent: false
});

This fragment supplies configuration for the existing editor. It does not initialize the editor or add heading support by itself. Match imports and package versions to the installed release.

showOnlyCurrent: false lets the interface show hints in empty nodes beyond the active selection. Leave the default behavior if hints should appear only where the author is working. Choose the behavior because it suits the form, rather than turning every option on while troubleshooting.

Add a rule that matches the decorated node

For hints on empty paragraphs and headings, put this rule in a stylesheet that reaches the actual editor content:

.tiptap :is(p, h1, h2, h3).is-empty::before {
  content: attr(data-placeholder);
  color: #667085;
  float: left;
  height: 0;
  pointer-events: none;
}

The .tiptap scope assumes that the application's editor root uses that class. Replace it with the real scope if necessary. Include only the heading levels the application supports. Generated text with height: 0 avoids making the hint a separate content line, while pointer-events: none lets the author click through to the editing surface.

The official documentation also shows a narrower rule for the first paragraph in a completely empty editor: .tiptap p.is-editor-empty:first-child::before. That rule is suitable for a single initial prompt. It will not show every empty heading or paragraph in a partially completed handover. Match the rule to the intended visibility policy.

Inspect the attribute, class, and style separately

In the running application, inspect an empty paragraph in the browser's Elements panel. Check these three observations:

Observation What to investigate if it fails
Empty node carries the intended hint attribute Extension registration, configured attribute name, and node-specific callback
Node carries the expected empty-node class Node content and the extension's visibility settings
Its ::before computed style has the expected generated text Stylesheet loading, selector scope, and overriding rules

If the attribute and class are present but the pseudo-element has no content, changing the editor's saved data will not fix the stylesheet. If the node contains actual spaces or other document content, inspect that content before assuming it is empty.

CSS modules or component-scoped styles can change how a selector reaches editor-generated nodes. Apply the application's documented global or deep styling mechanism rather than adding duplicate placeholder text to the document.

Account for nested and read-only content

Placeholder defaults to editable-mode decorations. A read-only reader page should show the report, not ask its reader to complete the authoring form. Keep that default unless the product deliberately needs a different presentation.

For nested content, includeChildren: true allows hints on nested textblock nodes. The current documentation distinguishes paragraphs and headings from wrapper nodes such as list items. If an empty paragraph inside a list needs a hint, inspect that paragraph; styling only the outer list item addresses a different node.

Use a visible label or heading for the editor as well. A hint disappears once typing begins, so it cannot be the only explanation of which field the author is completing. The native textarea guide explains the related label-versus-hint distinction for ordinary form fields.

Keep authoring hints out of the incident record

Start with an empty handover, enter a real incident heading and a symptom, then clear each node. Check that the appropriate hint returns and typing replaces its visual presence without leaving a second text layer.

Capture the supported JSON or HTML through the application's existing save route and inspect the actual document content. The hint should remain an authoring decoration, rather than a sentence inserted as report data. Reopen the saved report in the intended reader view and confirm that an unfilled field has not become the asserted symptom “Describe the symptom you observed.”

The Tiptap document integration guide covers loading supported content. Finish by checking the handover with both a completed field and an empty field: the author needs a useful cue, while the reader needs an accurate account of what was actually recorded.

Keep reading