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 are here! The long-awaited CSS feature has finally landed behind a flag in Chrome Canary. In this article, we'll take a look at an example of using them in conjunction with a clever, AI-based cropping solution from Cloudinary.
Before we get to container queries, let's discuss a widely available CSS feature: media queries. You've likely heard about media queries in CSS; they are frequently used in modern responsive web design, where we can change our application according to the browser's viewport width or the screen resolution. The most typical use-case for them would be to use "breakpoints" and render elements differently when the browser window gets resized.
Below you will see a classic example where top-level navigation displays its elements one after the other, but if the screen becomes smaller (smaller than 600px to be more precise in our case), the menu items will get stacked. This is achieved via the @media screen and (max-width: 600px) { ... }
media query. Try adjusting the screen, and the demo below should update accordingly - the menu items should be stacked and the menu's background colour also changes below 600 pixels.
See the Pen ZEebYYr by Cloudinary (@Cloudinary) on CodePen.
This is great, but what happens if we'd like to change how an element is rendered based on its parent container and not the size of the browsers? This is where container queries play an important role.
Container queries allow us to adjust elements based on the width of their parent. In the same way, how media queries would change the elements in navigation, container queries allow the reconstruction of children.
Let's consider a card component:
See the Pen jOBbayP by Cloudinary (@Cloudinary) on CodePen.
There are three cards present in the sample above, and if you're not using Chrome Canary, you should see three cards with the exactly the same black text. Do note that the dark grey background is indicating the width of the container.
However, if you open the same sample in Chrome Canary (with the appropriate flag enabled) you should see that based on the parent container's width, the text colour is changing. This behaviour is enabled by the following container CSS query:
@container (min-width: 360px) {
.card__title {
color: #f00;
}
}
@container (min-width: 640px) {
.card__title {
color: #00f;
}
}
Here's a screenshot of the above sample for convenience.
Let's add an image to the card. There are various strategies to achieve this - please 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 on this topic.
Our approach is going to be somewhat different from what these two wonderful authors have shown - instead of adding an img
element, we are going to add the image to the card via the background
property, like so:
.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>
Notice that the image we are using has been uploaded to Cloudinary, and for optimal results, we are using f_auto
, q_auto
and the h_350
parameter in the access URL. These will optimise the image before delivering a 350-pixel height version of it to the browser.
Now, if we place the card in the wide
container, we should be able to move the image and restructure the entire card by adding display:flex
to the card; and by using container queries, we can adjust the layout of elements and not only their colour we have seen before. Please see the example below.
See the Pen wvJKpxe by Cloudinary (@Cloudinary) on CodePen.
Placing the image into another container with a different size may result in the image losing its focus on what we are trying to show to our audience. In our example, we have a red dress which should be the focal point - the most critical item to be displayed in our image. Changing the layout around will mean that this important part from the image may not be visible as it is too distant (as shown in above example).
Luckily for us, we can utilise Cloudinary's cropping features, combined with AI aware object detection. Cloudinary can detect where the dress appears on the photo and create a crop around it. The result will be a perfect crop, showing exactly what we would like to display to our users. To achieve this we can use the following URL parameters in our Cloudinary access URL: g_cld-fashion_v2_dress,c_thumb,z_0.7
, and this will result in an image that focuses on the dress. Feel free to play around with the z
parameter, which allows us 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.
Please see a screenshot of the result below.
Using the above approach, we immediately solve the art direction problem since we are serving a differently cropped image for a different layout and we are leveraging container queries as well to display the same product information card with different layouts based on the parent container's width.
Container queries are a fantastic addition to CSS, and hopefully, we will get wider support for them in browsers. In a nutshell, they allow us to modify elements based on the size of their parents. Combining this with automatic AI-based cropping features with a tool like Cloudinary gives us excellent results when it comes to creating adaptive display cards.