How to Use Quill (with react-quill-new) and Distinguish <ul> vs <ol> Lists Using getSemanticHTML()
Rich text editors like Quill are great for React applications, but once you start saving editor content as HTML, you may notice something odd: both ordered and unordered lists are exported as <ol> elements.
This happens because Quill internally represents all lists using a single ordered list element and differentiates them using a data-list attribute. Unfortunately, this attribute is ignored by browsers when rendering HTML outside of Quill.
The result? Bullet lists may appear as numbered lists when displaying saved content.
The solution is to avoid using raw innerHTML and instead rely on Quill’s getSemanticHTML() method.
When using react-quill-new, you get access to the underlying editor instance directly in the onChange handler. This allows you to extract clean, semantic HTML that correctly reflects list types.
<ReactQuill
theme="snow"
value={value || ""}
onChange={(value, delta, source, editor) => {
setValue(editor.getSemanticHTML());
}}
/>By calling editor.getSemanticHTML(), Quill generates HTML intended for export and storage. This output respects the semantic meaning of blocks such as paragraphs and lists.
For example, without getSemanticHTML(), you might end up with HTML like this:
<ol>
<li data-list="ordered">First item</li>
<li data-list="ordered">Second item</li>
<li data-list="bullet">Bullet one</li>
<li data-list="bullet">Bullet two</li>
</ol>That structure renders everything as a numbered list.
With semantic HTML extraction, the output becomes:
<ol>
<li>First item</li>
<li>Second item</li>
</ol>
<ul>
<li>Bullet one</li>
<li>Bullet two</li>
</ul>This ensures that your content renders correctly everywhere — blog posts, previews, emails, or static pages.
In short, if you are storing or reusing Quill editor content, always prefer getSemanticHTML(). It preserves meaning, fixes list semantics, and saves you from subtle rendering bugs later.