How do I stop TipTap adding p tags to my li items?

Personally, after reading up on it, I’d say like @asawyer

I see that both are valid HTML, the output is a little different though. If it breaks some of the output, a quick fix to mimic previous behavior would be:

li > p { 
  margin: 0; 
  display: inline; 
}

Also, I do understand that if you’re upgrading it will be a while before you discover this new behavior. An editor makes a list and suddenly it looks different from all the other lists they made before.

We could change the defaults, but this has one very unfortunate side-effect: you’d never be able to use <p> elements in lists again (they would just be stripped). But that is valid HTML and has legitimate use cases. Using <p> inside <li> was also something you could already achieve in TinyMCE, so it would break things in different interesting ways which we’d need to find weird workarounds for :sweat_smile:

Just for perspective, this is what two LLMs that I consulted had to say about it:

TipTap uses ProseMirror’s schema. ProseMirror intentionally encourages:

<li>
  <p>…</p>
</li>

because:

  • a block-level node (like <p>) makes editing consistent
  • it avoids weird cursor behaviour
  • it allows adding multiple paragraphs inside one list item
  • it matches the HTML spec perfectly
  • TinyMCE doesn’t do this by default because it’s older and tries to emulate “Word-like” content, not necessarily semantic correctness.

So is <p> inside <li> more correct?
Yes. It is more semantically flexible and 100% valid HTML.

Plain text directly inside <li> is also valid, but wrapping content in a <p>:

  • better reflects that it’s a block of text
  • allows structured content inside a list item
  • aligns with modern editors
  • avoids ambiguous whitespace rules

This is why modern editors (TipTap, ProseMirror, CKEditor 5) use <p> inside <li>.