Handling `<strong>` spans in Portable Text without unwanted linebreaks
This 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:
- The block (e.g., a paragraph) should be rendered as a block-level element (like
<p>or<div>) - The spans within that block should be rendered inline (without wrapping divs)
- Decorators like
strongshould wrap the text content of those specific spans
The 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.
Correct Approach
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 Building a Custom Serializer
If you're building your own serializer, you need to:
- Render the block container (paragraph)
- Map through the children spans
- Apply marks to the text content inline, not as separate block elements
// 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.
Show original thread5 replies
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.