
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeThis is a common misunderstanding about how Portable Text's structure works! The key issue is that you shouldn't be rendering individual spans directly as separate elements - spans are meant to be rendered inline within their parent block.
Here's what's happening: In Portable Text, a block (like a paragraph) contains an array of children (spans), and those spans can have marks (like strong decorators). The proper way to render this is:
<p> or <div>)strong should wrap the text content of those specific spansThe problem you're experiencing happens when you try to render each span as its own component. Instead, you need to process the spans as part of the block rendering.
When using the official serializers like @portabletext/react, this is handled automatically. The block serializer processes all children spans together, applying marks inline:
import {PortableText} from '@portabletext/react'
// The library handles this correctly by default
<PortableText value={portableTextContent} />If you're building your own serializer, you need to:
// Simplified example
const renderBlock = (block) => {
return (
<p>
{block.children.map((span, index) => {
let text = span.text;
// Apply marks inline
if (span.marks?.includes('strong')) {
text = <strong key={index}>{text}</strong>;
}
if (span.marks?.includes('em')) {
text = <em key={index}>{text}</em>;
}
return text;
})}
</p>
);
};The critical point: don't wrap each span in a div. Spans are inline content that should flow together within their parent block. Only the block itself should be a block-level element.
If you're using a library and still experiencing this issue, you might be customizing the serializers incorrectly. Check the Portable Text introduction guide for more details on the data structure, and make sure your custom serializers for marks/decorators return inline elements, not block-level ones.
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.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store