How to enable and use image hotspot in Sanity with imageUrlBuilder?

10 replies
Last updated: Nov 29, 2025
Hi Friends!I am a student trying out sanity for a personal project. I am having a bit of trouble using the
image hotspot property. I added
hotspot:true
to the schema and I am using the
imageUrlBuilder
. But the hotspot still does not appear to be working. Are there some steps that I am missing? Do I need to add crop and hotspot to my GROQ query as well?
AI Update

Great question! Yes, you're on the right track, but there's an important detail about how hotspot data works with imageUrlBuilder that might be the missing piece.

When you set hotspot: true in your schema, that enables the hotspot UI in Sanity Studio where editors can set the focal point. However, you need to make sure you're passing the complete image object (including the hotspot data) to the imageUrlBuilder – not just the asset reference.

Here's what you need to check:

1. Your GROQ Query

Yes, you should explicitly include crop and hotspot in your GROQ query to ensure this data is returned:

*[_type == "yourType"] {
  image {
    asset->,
    hotspot,
    crop
  }
}

Without explicitly selecting these fields, they might not be included in your query results.

2. Pass the Full Image Object to urlBuilder

When using imageUrlBuilder, pass the entire image object (not just image.asset):

import imageUrlBuilder from '@sanity/image-url'

const builder = imageUrlBuilder(sanityClient)

// ✅ Correct - pass the full image object
const imageUrl = builder
  .image(image)  // Pass the whole image object with hotspot data
  .width(400)
  .height(300)
  .url()

// ❌ Wrong - don't pass just the asset
const wrongUrl = builder.image(image.asset).url()

The Image URL Builder will automatically use the hotspot and crop data when it's present in the image object you pass to it.

3. If Hotspot Still Doesn't Work

If you're using certain frontend frameworks (especially Next.js with the next/image component), the Image URL Builder might not fully respect the hotspot for object-fit: cover scenarios. In those cases, you can manually apply the hotspot using CSS:

function getPositionFromHotspot(hotspot) {
  if (!hotspot?.x || !hotspot?.y) return "center";
  return `${hotspot.x * 100}% ${hotspot.y * 100}%`;
}

// In your component
<img
  src={urlForImage(image).url()}
  style={{
    objectFit: 'cover',
    objectPosition: getPositionFromHotspot(image.hotspot)
  }}
/>

The hotspot values are coordinates where x and y are between 0-1, representing the percentage position from the left and top of the image.

Hope this helps! Let us know if you're still having issues after checking these points.

Show original thread
10 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.

Was this answer helpful?