How to model floated images within text content in Sanity?

8 replies
Last updated: Jun 16, 2022
Hi guys, I’m just starting off using Sanity (after years of WordPress work), and the first project I’m trying to set up is rebuilding an existing site and migrating the content. The first page I set out to do has an image that is floated in the written content (see screenshot) and I can’t for the life of me work out how to model this in Sanity.
Am I missing something, or is this breaking the idea of separation of concerns (content / design) etc. Is there a solution so I can keep the content working as is, or should I rethink it? Ideally I’m looking to migrate some clients for WP to Sanity so it is something they are likely to reach for
AI Update

Welcome to Sanity! This is a great question and one that many people coming from WordPress encounter. The good news is that Sanity absolutely supports this pattern - you're not missing anything, and you're thinking about it the right way.

In Sanity, this is handled using Portable Text, which is Sanity's rich text format. Unlike WordPress's traditional HTML-based editor, Portable Text stores content as structured JSON data. The key is that you can insert custom blocks (like images) directly within your text content, and then control how they're rendered on the frontend.

The Schema Setup

In your schema, define your content field as an array that includes both text blocks and image blocks with an alignment field:

{
  title: 'Body Content',
  name: 'body',
  type: 'array',
  of: [
    {
      type: 'block'  // Regular text paragraphs
    },
    {
      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: 'string',
          name: 'alt',
          title: 'Alternative text'
        }
      ]
    }
  ]
}

This allows your content editors to insert images directly into the text flow, just like in WordPress. The alignment field lets them specify how the image should float.

Rendering on the Frontend

When you render this content, you'll use a Portable Text renderer (like @portabletext/react for React) and define custom components for how images should display:

import { PortableText } from '@portabletext/react'

const components = {
  types: {
    blockImage: ({value}) => (
      <img 
        src={urlFor(value.image).url()} 
        alt={value.alt}
        className={`float-${value.alignment}`}
        // or style={{float: value.alignment}}
      />
    )
  }
}

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

About Separation of Concerns

You're absolutely right to think about this! The way Sanity handles it is actually a nice middle ground: the content editor specifies the intent (this image should be positioned to the left), but your frontend code determines the implementation (the actual CSS classes, breakpoints, responsive behavior, etc.). This is different from WordPress where HTML/CSS is often directly embedded in content.

This approach gives you the best of both worlds - editors get the control they need to create the layouts they want, but you maintain full control over how those layouts actually work across different devices and contexts.

Preview Considerations

As mentioned in this community discussion, the image won't preview with the float styling directly in the Portable Text editor. However, you have a couple of options:

  1. Use the iframe preview pane plugin to show a live preview of your actual page alongside the editor
  2. Create a custom preview component for your image blocks that renders them with the appropriate styling in the editor itself (see Customizing the Editor)

Your clients coming from WordPress will find this familiar in the Studio interface (they can insert images inline between paragraphs), but you get much more flexibility in how that content gets rendered across web, mobile, email, or any other platform. This is the power of structured content - write once, render appropriately everywhere.

Show original thread
8 replies
I am interested in this myself, because the idea of content being structured is very bright and practical, in a property-value sort of way. Things having attributes, all that jazz. And I totally get the idea behind a raw/pure compartmentalization of the kind of content portable text is, versus pulling it back and forth into different already-compiled formats.
But this software, as a CMS-like place to go for people to edit content...any regular person will want to treat the editor like the ones they've seen every other place, and will be weirded out when they can't. Especially, certainly if they're attempting to bring over existing content.

The way I have it right now, is I can put an image in the text, but the image has its own separate field for an alignment value, in the form of a radio (left, center, right).

It doesn't preview like that in the editor (although I am sure someone has figured that out) but it works great on my front end and I can even re-use the value from the data to automatically generate the class name rather than applying a style directly.


{
            title: 'Additional Information',
            name: 'additionalInformation',
         
            type: 'array',
            of: [
                {
                    type: 'block',
                    
                },
                {
                    type: 'object',
                    title: 'Image',
                    name: 'blockImage',
                    fields: [
                        {
                            type: 'image',
                            name: 'inlineImage',
                        },
                        {
                            type: 'string',
                            layout: 'list',
                            name: 'alignment',
                            options: {
                                list: [
                                    { title: 'Left', value: 'left' },
                                    { title: 'Center', value: 'center' },
                                    { title: 'Right', value: 'right' }
                                ],
                                layout: 'radio',
                                direction: 'horizontal'
                            }
                        }
                    ]
                }
            ],
        },

user H
Ah right, so you just sit it in between text content where you want it. This is probably fine… ideally (long term), it would be great to have it behave appropriately in the preview, but I guess I can set up the Sanity editor to show a preview of the actual page side by side to the content being edited (when I say I can, I’ve seen that it is possible).
Preview pane is definitely the way to go. I just did this with tailwind on the front and then options to float left and float right etc. There's also both mobile and desktop previews in the window so you can get a couple of views in the pane.Here's a link to the preview pane plugin:

https://www.sanity.io/plugins/iframe-pane
Amazing. Thanks
user J
and
user S
If you did need an image truly inline in the editor, the block type has an "of" property where you can stick other fields. I threw up an example earlier this week where you could drop a reference to another document type (in the example it was a Person) right in the middle of a line of text, speculating that on various front ends you could ask for anything you needed in that context so long as the connection was made there ( just their name on one page, for example, or spinning out a mailto: link with their email and their name as the inner text.
I have thought about something like that just showing a picture preview, but when it comes to aligning, having that be eventually floated on the real page and just stranded like an island in the preview seems like a different kind of impractical, so that's why I haven't done it with my two total ideas I've had so far
😃
Preview definitely sounds like it because it's direct and handles what they'll wanna know, which is, what's going to happen to my stuff if I make these decisions, and what will the adoring public see
😃
Hi everyone!y’all did a great job already with bringing up the preview pane.
👏I just wanted to add, that there is a good way to render objects, references etc. within the Portable Text Editor in Sanity:
Customizing the Editor .There is also a wonderful guide by
user Y
which explains how to render a youtube player into the editor .
And for anyone, who would like to see it in action between schema, studio, editor and front-end can have a look at some of
my snippets .
Hope that helps!
☺️
user J
That's super cool! I didn't make the connection before that it was like the document previews where you "tee up" the component property by loading the "select" (including a kind of dereferencing it seems because I was able to get my image address naturally in place.

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.

Was this answer helpful?