Joint session with Vercel: How to build intelligent storefronts (May 15th)

How do I render the image in Sanity blockcontent into a custom image component?

4 repliesLast updated: Nov 29, 2025

How is it that i render the image in the blockcontent into a custom image component? like in a blogpost where I want to display images in the body section that are uploaded in the body which has block content type… this link (https://github.com/sanity-io/block-content-to-react ) didn't help me, as specifying imageOptions in BlockContent displays images very plainly, i couldn't control the width based on screen sizes and image zoom feature that I could implement if I could use a custom image component
AI Update

I can help you render images in Portable Text with a custom image component! The key is using the modern @portabletext/react library (which replaces the deprecated block-content-to-react) with custom serializers.

Here's how to set up a custom image component in your Portable Text:

import { PortableText } from '@portabletext/react';
import Image from 'next/image'; // or your preferred image component
import imageUrlBuilder from '@sanity/image-url';

// Set up image URL builder
const builder = imageUrlBuilder(client);

function urlFor(source) {
  return builder.image(source);
}

// Your custom image component with full control
const CustomImageComponent = ({ value }) => {
  if (!value?.asset?._ref) {
    return null;
  }

  return (
    <div className="my-8 relative">
      <Image
        src={urlFor(value).width(800).url()}
        alt={value.alt || 'Blog image'}
        width={800}
        height={600}
        className="w-full h-auto cursor-zoom-in"
        onClick={() => {
          // Your custom zoom logic here
        }}
        sizes="(max-width: 640px) 100vw, (max-width: 1024px) 80vw, 800px"
      />
      {value.caption && (
        <p className="text-sm text-gray-600 mt-2">{value.caption}</p>
      )}
    </div>
  );
};

// Define your custom components
const components = {
  types: {
    image: CustomImageComponent,
    // You can add other custom types here
  },
  marks: {
    // Custom marks like links, highlights, etc.
  },
};

// Use in your blog post
function BlogPost({ post }) {
  return (
    <article>
      <h1>{post.title}</h1>
      <PortableText 
        value={post.body} 
        components={components}
      />
    </article>
  );
}

Important differences from the old library:

For responsive sizing, you can:

For zoom functionality, you can integrate libraries like:

The custom serializers guide has more examples of advanced customization. The key is that with @portabletext/react, you get the full value object containing all your image data, giving you complete control over rendering!

Show original thread
4 replies

Was this answer helpful?

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.

Related contributions