Adding image control fields in Block Content in Sanity
Looking at adding image alignment controls (left/right, center, sizing) to Block Content/Portable Text, there are a few solid approaches. The community has worked through this exact challenge since Portable Text doesn't include alignment options by default.
Recommended Approach: Custom Image Block with Alignment Fields
The most common pattern is to create a custom image object within your Portable Text array that includes alignment and sizing options. Here's a working example from the Sanity community discussion:
{
title: 'Body Content',
name: 'body',
type: 'array',
of: [
{
type: 'block',
},
{
type: 'object',
title: 'Image',
name: 'blockImage',
fields: [
{
type: 'image',
name: 'image',
options: {
hotspot: true
}
},
{
type: 'string',
name: 'alignment',
title: 'Alignment',
options: {
list: [
{ title: 'Left', value: 'left' },
{ title: 'Center', value: 'center' },
{ title: 'Right', value: 'right' }
],
layout: 'radio',
direction: 'horizontal'
}
},
{
type: 'number',
name: 'width',
title: 'Width (%)',
validation: Rule => Rule.min(10).max(100)
},
{
type: 'string',
name: 'alt',
title: 'Alt text'
}
]
}
]
}This approach lets editors insert images between text blocks and choose alignment (left/right/center) and sizing. The image sits as its own block in the content flow, which works well for float-left, float-right, and centered images.
Rendering on the Frontend
When rendering with @portabletext/react or similar libraries, you'd handle the custom block:
import { PortableText } from '@portabletext/react'
import imageUrlBuilder from '@sanity/image-url'
const builder = imageUrlBuilder(client)
const urlFor = (source) => builder.image(source)
const components = {
types: {
blockImage: ({ value }) => (
<figure
className={`image-${value.alignment}`}
style={{
width: value.width ? `${value.width}%` : 'auto',
float: value.alignment === 'left' || value.alignment === 'right'
? value.alignment
: 'none'
}}
>
<img
src={urlFor(value.image)}
alt={value.alt}
/>
</figure>
)
}
}
<PortableText value={content} components={components} />Making it Preview Better in Studio
You can customize how custom blocks appear in the Portable Text Editor to show a preview of your image blocks. This helps editors see how alignment will look:
{
type: 'object',
name: 'blockImage',
// ... fields as above
preview: {
select: {
image: 'image',
alignment: 'alignment',
width: 'width'
},
prepare({ image, alignment, width }) {
return {
title: `Image (${alignment}, ${width || 100}%)`,
media: image
}
}
}
}For even better in-editor visualization, check out the guide on adding custom YouTube embeds which shows the pattern for rendering custom components directly in the editor.
Using Preview Pane for Real-Time Feedback
As the community strongly recommends, the iframe-pane plugin is excellent for seeing real-time previews of how your alignment and sizing choices render on your actual site. This gives editors immediate visual feedback side-by-side with the content they're editing, including mobile and desktop views.
Alternative: Inline Images
For truly inline images (flowing within text like an emoji), you can use the block type's of property to add inline objects with options.inline: true. However, this is less common for alignment use cases since floated/aligned images typically work better as standalone blocks between paragraphs rather than mid-sentence.
Demo Implementations
While there isn't an official Sanity demo specifically for image alignment, you can find community examples in:
- The Sanity community thread with working code
- Bobinska's Portable Text snippets showing schema, editor, and frontend rendering
The key insight: separation of concerns is maintained because you're storing structured data (alignment: "left", width: 50) rather than inline styles or HTML. Your frontend then interprets this data to apply appropriate CSS classes or styles, giving you flexibility to change presentation without touching content. This is the Portable Text philosophy in action.
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.