Best practice for specifying alt text for images in block text using Sanity

8 replies
Last updated: Jul 20, 2021
Hi, is there a best practice to specify alt text for an image embedded in a block text (I'm using block-content-to-react)?
AI Update

The best practice for adding alt text to images embedded in block content is to extend your image block definition with a custom alt field. Here's how to set it up:

In your schema definition:

{
  name: 'blockContent',
  type: 'array',
  of: [
    {
      type: 'block'
    },
    {
      type: 'image',
      options: {hotspot: true},
      fields: [
        {
          name: 'alt',
          type: 'string',
          title: 'Alternative text',
          description: 'Important for SEO and accessibility.',
          validation: Rule => Rule.required()
        }
      ]
    }
  ]
}

This adds an alt text field that appears directly below the image upload in Sanity Studio, making it easy for editors to add descriptive text for each image.

When rendering (using the current recommended approach):

Note that @sanity/block-content-to-react was deprecated in 2022. You should now use @portabletext/react instead. Here's how to render your images with alt text using the modern approach:

import {PortableText} from '@portabletext/react'
import imageUrlBuilder from '@sanity/image-url'

const builder = imageUrlBuilder(client)

const components = {
  types: {
    image: ({value}) => (
      <img
        src={builder.image(value).url()}
        alt={value.alt || 'Image'}
      />
    )
  }
}

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

The key differences from the old library:

  • Use components prop instead of serializers
  • Use value prop instead of blocks
  • Access the image data through value instead of node in your component

This approach gives you full control over how images are rendered and ensures the alt text stored in your content is properly used in your HTML output. You can learn more about custom blocks in Portable Text in the official documentation.

Show original thread
8 replies
Do you mean the best practice to set it up in Sanity?
Yes, so that an editor could specify it manually
Okay, thanks for clarifying. One approach would be:
1. In Sanity, create an
image
object. Let’s say this lives at schemas/objects/customImage.js:
export default {
  name: "customImage",
  title: "Image",
  type: "image",
  options: {
    hotspot: true,
  },
  fields: [
    {
      title: "Alternative Text",
      name: "alt",
      type: "string",
      validation: Rule => Rule.required(),
      options: {
        isHighlighted: true,
      },
    },
  ],
};
2. Import that
image
object into your portable text schema:
import customImage from './customImage';

export default {
  name: "content",
  title: "Content",
  type: "array",
  of: [
    {
      type: "block",
      styles: [
        // ...
      ],
      marks: {
        decorators: [
          // ...
        ],
        annotations: [
          // ...
        ],
      },
    },
    customImage,
  ],
}
This will let you and your editors add images to your portable text (block content) and set alt text in a field that will show directly below the image upload widget. If you’d rather the alt text hide behind the Edit details button, you can get rid of
options.isHighlighted
(or set it to
false
).
Okay, thanks for clarifying. One approach would be:
1. In Sanity, create an
image
object. Let’s say this lives at schemas/objects/customImage.js:
export default {
  name: "customImage",
  title: "Image",
  type: "image",
  options: {
    hotspot: true,
  },
  fields: [
    {
      title: "Alternative Text",
      name: "alt",
      type: "string",
      validation: Rule => Rule.required(),
      options: {
        isHighlighted: true,
      },
    },
  ],
};
2. Import that
image
object into your portable text schema:
import customImage from './customImage';

export default {
  name: "content",
  title: "Content",
  type: "array",
  of: [
    {
      type: "block",
      styles: [
        // ...
      ],
      marks: {
        decorators: [
          // ...
        ],
        annotations: [
          // ...
        ],
      },
    },
    customImage,
  ],
}
This will let you and your editors add images to your portable text (block content).
Thank you, how can I reference the alt field? My code:
Thank you, how can I reference the alt field? My code (
asset.alt
doesn't work):
const serializers = {
    types: {
      image: ({ node: { asset } }) => (
        <picture>
          <img
            src={urlForImage(asset)}
            alt={urlForImage(asset.alt)} />
        </picture>
      ),
    }
  };
I believe
alt
will be a child of
node
, so you’ll want to include it when you destructure
node
. Perhaps:

const serializers = {
    types: {
      image: ({ node: { asset, alt } }) => (
        <picture>
          <img
            src={urlForImage(asset)}
            alt={alt} />
        </picture>
      ),
    }
  };
You're right, it works. Thank you for helping

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?