DEV Community

John Serrao
John Serrao

Posted on

Handling Imagery with CSS

Problem Set

I've been teaching people to code for almost seven years now, which has exposed me to hundreds of junior developers. The number one area where I see people either not understanding or overthinking solutions is with imagery.

Below are some common ways to deal with images. I'll try to keep this updated as techniques improve over time.

Portrait or Landscape?

These terms refer to the aspect ratio of the image where landscape photos are typically are wider than they are tall, while portrait photography is typically taller than it is wide. There are also square images, which would be as tall as they are wide. You can classify any image into one of those three categories.

Basic Responsive Image (landscape)

Most imagery is in landscape aspect ratio and you need a baseline technique for dealing with them. I treat them as a full-width break on the page and have them 'snap' to the size of the screen.

img {
  display: block;
  height: auto;
  max-width: 100%;
}
Enter fullscreen mode Exit fullscreen mode

Working Demo

This is tried and true, works across any device and is an ideal pair with responsive, landscape images in the foreground of your page. They create impact and work just about anywhere.

Responsive Background Image (landscape) With Clipping

Background images are a bit trickier because they don't take up any space. They are in the background of an HTML element, just window dressing. So you have to get more inventive.

If you don't mind some clipping of your image, try background-size: cover:

.container-with-bg {
  background-image: url(path/to/your-image.jpg);
  background-position: center center;
  background-size: cover;
  height: 50vh;
}
Enter fullscreen mode Exit fullscreen mode

Working Demo

This says to the browser:

Make the element take 50% of the height of the screen (100% width is default) and center the background image into that space.

The key part to understand is that background-size puts the browser in charge of your display. The height and width are variable in this example so the sides of the images will occasionally be trimmed (at really wide or narrow screens). This can be acceptable for a lot of background images.

Responsive Background Image (landscape) - Exact Sizing

If you have a background image AND you know the aspect ratio of it, you can put a little hack into use. A little known but powerful quirk of HTML elements is that their padding-top and padding-bottom values equal the width of the container.

/**
 * How did I get 66.67% for the padding-top?
 * Original dimensions of the image (4242 x 2828px)
 * Get aspect ratio (2828/4242 * 100) 
 */
.container-aspect-ratio {
  background-image: url(path/to/your-image.jpg);
  background-position: center center;
  background-repeat: no-repeat;
  background-size: contain;
  height: 0px;
  padding-top: 66.67%;
}
Enter fullscreen mode Exit fullscreen mode

Working Demo

Looks a bit weird, right? If we have a container that is 1000px wide, the padding-top: 50% would actually equal 500px when rendered. Don't believe me? Check it out.

If you're curious, you probably notice that this padding hack creates an aspect-ratio, where the container is half as tall as it is wide. We can use this to our advantage:

  • Set height: 0 on your container (so the padding-top will become the only part of the container you see).
  • Add background-size: contain which will size your image EXACTLY to it's container
  • Set the padding-top to the aspect ratio of your image

Now you've got a perfect background-image that doesn't clip your image. (CSS-tricks.com has a more thorough rundown if you want it.)

How to Get Text on Top of Background Image with No Clipping

Our previous example creates a container with no height - so how do we get text on top of it? You can absolutely position the text on top of the relatively positioned container with the background image in it:

.text {
  bottom: 0;
  position: absolute;
  width: 100%;
}
Enter fullscreen mode Exit fullscreen mode

Working Demo - same as above.

Oldest comments (0)