Joint session with Vercel: How to build intelligent storefronts (May 15th)

How to declare nested ul/ol list block types for PortableText in Sanity?

1 replyLast updated: Nov 29, 2025

Hello, I have these nested lists,
ul
and
ol
, but I don't know how to declare the block type of these lists in order to use them in PortableText
AI Update

Looking at your question about declaring nested lists (ul and ol) in PortableText, I can help clarify how lists work in Sanity's block type schema.

The key thing to understand: Lists in PortableText are actually configured through the block type itself, not as separate types. By default, the block type in Sanity already supports lists - you don't need to declare them separately.

Here's how to configure lists in your schema:

defineField({
  name: 'content',
  type: 'array',
  of: [
    {
      type: 'block',
      // Configure which list types are available
      lists: [
        {title: 'Bullet', value: 'bullet'},
        {title: 'Numbered', value: 'number'}
      ],
      // Configure list item levels (for nesting)
      styles: [
        {title: 'Normal', value: 'normal'},
        {title: 'H1', value: 'h1'},
        // ... other styles
      ],
      marks: {
        // ... your marks configuration
      }
    }
  ]
})

Important points about rendering:

query {
  post {
    _rawContent  // Use _raw prefix
  }
}
import {PortableText} from '@portabletext/react'

const components = {
  list: {
    bullet: ({children}) => <ul className="custom-bullet-list">{children}</ul>,
    number: ({children}) => <ol className="custom-numbered-list">{children}</ol>
  },
  listItem: {
    bullet: ({children}) => <li className="custom-bullet-item">{children}</li>,
    number: ({children}) => <li className="custom-number-item">{children}</li>
  }
}

<PortableText value={content} components={components} />

For nested lists: Sanity's block editor supports nested lists out of the box. Users can indent list items in the editor using Tab/Shift+Tab, and the nesting structure is automatically preserved in the PortableText data.

The confusion often comes from the fact that lists in PortableText are stored as blocks with listItem and level properties rather than as nested HTML-like structures. The rendering libraries handle converting this flat structure into proper nested HTML automatically.

If you're still seeing issues with lists not rendering correctly, make sure you're:

Show original thread
1 reply

Was this answer helpful?

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Related contributions