Showing the middle of an image
Tags: css
Published: 2022-08-21 09:47:50

I've found a [cute dog photo on Unsplash](https://unsplash.com/photos/zBc2AbHTYCs) and I'm using it as a hero image. Since it's longer than it is tall, then I want to constrain the height. Except then it only shows the top of the image. So how to show the middle?

## Set up
Here's how I have my hero image set up.

HTML:
```html
<div class="hero">
  <img src="https://images.unsplash.com/photo-1658786335136-0b3e83dcb63a" alt="cute dog">  
</div>
```

CSS:
 ```css
.hero {
  max-height: 100vh;
  overflow: hidden;
}

img {
  max-width: 100%;
}
```

I have an image inside a hero div.

For the .hero div, I'm setting the max height to be 100% of the viewport height, as you're likely to have on a hero section.

Once you set the height of the div, then the image will spill out of it. `overflow: hidden;` stops that - and also therefore cuts the image off so only the top is shown.

On the image, `max-width: 100%;` means it will always fill the width of the browser window no matter how big or small that is.

There are two ways (that I've found) of fixing this image so it will show the cute dog in the middle of it.

## Option 1: positioning
The image is all there, it's just the bottom bit that's being cut off. We can change which bit is being cut off by moving the image. Since we want to show the centre of it, we know that you can do that like this:
```css
img {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
}
```
Except that doesn't work. That's because it doesn't know the height of the parent. I set it as max-height, rather than height. It means it can't work out what to do with `top: 50%;`. On seeing that CSS is asking "But 50% of what?"

The solution is to add an explicit height to the hero div:
```css
.hero {
  height: 100vh;
}
```
Which is fine with this image, but what if we had a really wide and short image? Then it would be stretched. I can't just tell this to be height 100% because it still doesn't know what that's 100% of.

The solution is to tell it that the HTML and body are 100%, as is the hero:
```css
html,
body,
.hero {
  height: 100%;
}
```
So now it knows that the height of all three elements are 100% of the page. But since .hero has a max-height, then if the height is taller than the max-height, it'll go with the max-height.

Here's all the CSS code for this solution:
```css
.hero {
  max-height: 100vh;
  overflow: hidden;
}

img {
  max-width: 100%;
}

/* Show the centre of the image using positioning */
html,
body,
.hero {
  height: 100%;
}

img {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
}
```

## Option 2
This option involves our old centring friend, the flexbox.
```css
.hero {
  display: flex;
  align-items: center;
}
```
And we're looking at a cute dog.

This does complicate things if you also have text in your hero section. But if you do it's likely to be on top of the image, so then either the image or the text will need to be absolutely positioned anyway.

### The cute dog
I know I keep saying how cute it is. So here it is, along with the code, so you can play with it.

{% codepen https://codepen.io/nicm42/pen/VwXrRyP %}

I did disappear for a while, because it too hot to do anything. Hopefully now that's the worst of summer over.