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

10 replies
Last updated: Mar 9, 2022
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
Hi User. Is
hotspot: true
inside of an
options
object (as opposed to being directly on the image)?
It is inside an options object (see code below) I can see the interface on sanity, and adjust the hotspot, I just don't see the changes in my app.
    {
      name: "mainImage",
      title: "Main image",
      type: "image",
      options: {
        hotspot: true,
      },
    },
My expectation is that the faces would stay in focus as I resize, because that is where I centered the hotspot. But you can see in the video below that they are being cut off.
sorry about the video quality...probably not the most helpful haha
Ah! That’s very helpful. Thanks! What does your front end code look like?
Here is the gihub repo .The
grid container component houses all the profile cards . and the GROQ Query is passed in from the team component .Could my styling be impacting it?
Hey
user A
! Wondered if you had a chance to look into this more? Im still a bit stuck on it
Could you please try changing your
mainImage
projection here so it looks like this:

mainImage{
  ...,
  asset->,
}
My thought is that because the projection currently doesn’t ask for crop and hotspot data, it can’t get applied. Hopefully this gets things working but please let me know if it doesn’t.
Thanks User! adding this to the query and passing in
mainImage.asset
to the url builder seemed to do the trick!
Great! Happy to hear that. 🙌

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?