Skip to main content

Container Queries Meet AI-Based Cropping

5 min read

Older Article

This article was published 5 years ago. Some information may be outdated or no longer applicable.

Please note that the demos in this article should be viewed in Chrome Canary. When writing this article, you need to enable container queries via chrome://flags to enjoy the demos fully.

For an in-depth overview on container queries, please read Say Hello to CSS Container Queries by Ahmad Shadeed

Container queries have arrived. The long-awaited CSS feature has finally landed behind a flag in Chrome Canary. We’ll look at how to pair them with Cloudinary’s AI-based cropping.

Media Queries

Before we get to container queries, let’s talk about what we already have: media queries. You’ve probably used them. They let us reshape our application based on the browser’s viewport width or screen resolution. The most typical use case is setting breakpoints and rendering elements differently when the browser window gets resized.

Below is a classic example where top-level navigation displays items in a row. But when the screen shrinks below 600px, the menu items stack vertically. The @media screen and (max-width: 600px) { ... } media query makes this happen. Try adjusting the screen. The demo below should update accordingly, and the menu’s background colour also changes below 600 pixels.

See the Pen ZEebYYr by Cloudinary (@Cloudinary) on CodePen.

That’s useful. But what happens when we want to change how an element renders based on its parent container rather than the browser size? That’s where container queries step in.

Container Queries

Container queries let us adjust elements based on the width of their parent. Just as media queries reshape navigation items, container queries reshape children based on their container.

Let’s consider a card component:

See the Pen jOBbayP by Cloudinary (@Cloudinary) on CodePen.

Three cards sit in the sample above. If you’re not using Chrome Canary, you’ll see three cards with identical black text. The dark grey background indicates the container width.

Open the same sample in Chrome Canary (with the flag enabled) and you’ll see the text colour shifting based on the parent container’s width. This behaviour comes from the following CSS:

@container (min-width: 360px) {
  .card__title {
    color: #f00;
  }
}

@container (min-width: 640px) {
  .card__title {
    color: #00f;
  }
}

Here’s a screenshot for convenience.

Working with images

Let’s drop an image into the card. There are various strategies for this. Take a look at these two excellent articles: Component-level art direction with CSS Container Queries by Sara Soueidan and Container Queries are actually coming by Andy Bell.

Our approach differs from what those two authors have shown. Instead of adding an img element, we’ll attach the image to the card via the background property:

.card__image {
  background-image: url('https://res.cloudinary.com/tamas-demo/image/upload/h_350,q_auto,f_auto/v1620728383/j3qdcbvp1w5wabqlcoyg.jpg');
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center center;
  height: 350px;
}
<div class="card__image"></div>

The image has been uploaded to Cloudinary. For optimal results, we’re using f_auto, q_auto and the h_350 parameter in the access URL. These optimise the image before delivering a 350-pixel-height version to the browser.

Now, placing the card in the wide container, we can shift the image and restructure the entire card by adding display:flex. With container queries, we can adjust layout (not just colour, as we saw before). See the example below.

See the Pen wvJKpxe by Cloudinary (@Cloudinary) on CodePen.

Placing the image into a differently sized container can cause the focal point to drift. In our example, there’s a red dress that should be the star of the image. Change the layout, and that important part might disappear from view (as the above example shows).

Luckily, Cloudinary’s cropping features can help. Combined with AI-aware object detection, Cloudinary can spot where the dress appears in the photo and crop around it. The result is a precise crop showing exactly what we want our users to see. To pull this off, we use the following URL parameters: g_cld-fashion_v2_dress,c_thumb,z_0.7. This produces an image that focuses squarely on the dress. Feel free to play with the z parameter to zoom in and out on the crop.

See the Pen jOBbxEB by Cloudinary (@Cloudinary) on CodePen.

Cloudinary can detect other objects as well using Artificial Intelligence via their AI Content Analysis - Object Aware Cropping feature. Check out the link for all the available options.

Here’s a screenshot of the result.

With this approach, we solve the art direction problem immediately. We’re serving a differently cropped image for a different layout, and we’re using container queries to display the same product card with different layouts based on the parent container’s width.

Conclusion

Container queries are a brilliant addition to CSS, and hopefully browser support will widen soon. In short, they let us modify elements based on the size of their parents. Pair that with automatic AI-based cropping from a tool like Cloudinary, and you get excellent results when building adaptive display cards.