# Container Queries Meet AI-Based Cropping

Source: https://tpiros.dev/blog/container-queries-meet-ai-based-cropping

> 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](https://ishadeed.com/article/say-hello-to-css-container-queries/)

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.

<p class="codepen" data-height="520" data-theme-id="dark" data-default-tab="result" data-user="Cloudinary" data-slug-hash="ZEebYYr" style="height: 520px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="ZEebYYr">
  <span>See the Pen <a href="https://codepen.io/team/Cloudinary/pen/ZEebYYr">
  ZEebYYr</a> by Cloudinary (<a href="https://codepen.io/Cloudinary">@Cloudinary</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>

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:

<p class="codepen" data-height="520" data-theme-id="dark" data-default-tab="html,result" data-user="Cloudinary" data-slug-hash="jOBbayP" style="height: 520px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="jOBbayP">
  <span>See the Pen <a href="https://codepen.io/team/Cloudinary/pen/jOBbayP">
  jOBbayP</a> by Cloudinary (<a href="https://codepen.io/Cloudinary">@Cloudinary</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>

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:

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

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

Here's a screenshot for convenience.
![](https://res.cloudinary.com/full-stack-training/image/upload/f_auto,q_auto,w_800/v1620734379/blog/media-query-chrome-canary.png)

# 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](https://www.sarasoueidan.com/blog/component-level-art-direction-with-container-queries-and-picture/) and [Container Queries are actually coming by Andy Bell](https://piccalil.li/blog/container-queries-are-actually-coming/).

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:

```css
.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;
}
```

```html
<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.

<p class="codepen" data-height="520" data-theme-id="dark" data-default-tab="css,result" data-user="Cloudinary" data-slug-hash="wvJKpxe" style="height: 520px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="wvJKpxe">
  <span>See the Pen <a href="https://codepen.io/team/Cloudinary/pen/wvJKpxe">
  wvJKpxe</a> by Cloudinary (<a href="https://codepen.io/Cloudinary">@Cloudinary</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>

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.

<p class="codepen" data-height="520" data-theme-id="dark" data-default-tab="result" data-user="Cloudinary" data-slug-hash="jOBbxEB" style="height: 520px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="jOBbxEB">
  <span>See the Pen <a href="https://codepen.io/team/Cloudinary/pen/jOBbxEB">
  jOBbxEB</a> by Cloudinary (<a href="https://codepen.io/Cloudinary">@Cloudinary</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>

<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

> Cloudinary can detect other objects as well using Artificial Intelligence via their [AI Content Analysis - Object Aware Cropping](https://cloudinary.com/documentation/cloudinary_ai_content_analysis_addon#object_aware_cropping) feature. Check out the link for all the available options.

Here's a screenshot of the result.

![](https://res.cloudinary.com/full-stack-training/image/upload/f_auto,q_auto,w_800/v1620734791/blog/media-query-image.png)

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.
