How do I render the image in Sanity blockcontent into a custom image component?
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:
- The prop is now
value(notnode) - this gives you access tovalue.asset,value.hotspot,value.crop, and any custom fields - Components are organized under
types,marks,list, andblockcategories - You have complete control over the rendered output
For responsive sizing, you can:
- Use CSS classes with media queries
- Use the
sizesattribute with Next.js Image - Build different image URLs with Sanity's image builder:
urlFor(value).width(640).url()for mobile, etc.
For zoom functionality, you can integrate libraries like:
- react-medium-image-zoom
- react-image-lightbox
- Or build your own modal
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 thread4 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.