Responsive web design is essential for providing users a positive experience on your website or web application.
Responsive web design is crucial for delivering a positive user experience on websites and web applications. With over 55% of all web traffic coming from mobile devices and 92.3% of internet users accessing the internet via mobile phones, ensuring responsiveness is more important than ever.
As more users access the web through mobile devices like smartphones and tablets, responsive design ensures that web pages render well across different screen sizes.
Through flexible layouts, images, and CSS media queries, responsive design detects a user's screen size and orientation to provide an optimal viewing experience.
However, the approach of relying solely on traditional media queries for responsive web design where elements adapted primarily based on the size of the entire viewport has been proven inadequate for complex scenarios such as where you want a sidebar navigation menu to adjust its width based on the available space within its container or changing the styles of an element based on the width of its parent element.
When relying on the traditional responsive design of viewport size, elements may resize or overflow awkwardly, leading to poor user experiences.
This is where Tailwind Container Queries come into play. With the recent introduction of container queries in Tailwind v3.2, creating responsive layouts, texts, and images on your website has become effortlessly accessible.
This article will teach you how to use Tailwind container queries to build responsive websites quickly.
If you are excited to read about this new approach to responsive web design as much as I am writing about it, then let’s dive straight in. 🚀
Media queries are a CSS feature that enables you to apply different styles to your website or application based on the device's characteristics. These characteristics can include screen size
, resolution
orientation
, aspect ratio
, print
, and more
While CSS media queries are primarily designed for visual displays, they can target a variety of devices and user agents using keywords like print
for printer output or screen
for traditional displays, enabling tailored presentational experiences across diverse platforms.
1@media screen, print {
2 div {
3 color: #000000;
4 font-weight: 500;
5 }
6}
The CSS Media Query ensures that CSS is applied only when the browser and device environment meet the criteria you set. This adaptability allows you to specify a media query and a block of CSS to apply to the document if and only if the media query matches the device on which the content is being used. For example, in the code snippet below, we set the default font size to be 16px
, and then, adjust the font size based on the device viewport.
CSS media queries allow you to create different styles for different screen sizes. Here's an example code snippet:
1/* Default styles */
2body {
3 font-size: 16px;
4}
5
6/* Styles for small screens */
7@media screen and (max-width: 480px) {
8 body {
9 font-size: 14px;
10 }
11}
12
13/* Styles for medium screens */
14@media screen and (min-width: 481px) and (max-width: 768px) {
15 body {
16 font-size: 15px;
17 }
Here are a few examples of common media queries for different screen sizes:
(< 480px)
:1@media only screen and (max-width: 480px) { /* styles */ }
(480px - 768px)
:1@media only screen and (min-width: 480px) and (max-width: 768px) { /* styles */ }
(768px - 992px)
:1@media only screen and (min-width: 768px) and (max-width: 992px) { /* styles */ }
Despite their usefulness, media queries have several drawbacks for adaptive web design:
1. Increased Complexity and Maintenance:
2. Cross-Browser Compatibility Issues:
3. Difficulty in Predicting User Behavior:
4. Potential Performance Impact:
5. Limitations of Viewport-Based Design:
CSS Media Queries apply different styles to different screen sizes. New CSS features, such as Grid Layout and Flexbox, provide more efficient and flexible ways to create responsive designs without relying on media queries.
While media queries are effective for regular responsive web development needs, they fall short when it comes to complex scenarios. In the next section, I will delve into the limitations of media queries, highlighting the need for alternatives in such cases.
TailwindCSS is a CSS framework that enhances your productivity in responsive design. It provides low-level utility classes that can be directly applied to HTML markup, allowing you to create unique frontend design without the need for extensive custom styling. Tailwind CSS includes a mobile-first breakpoint system that allows unprefixed utilities to apply to all screen sizes, while prefixed utilities target larger screens.
This means that unprefixed utilities, such as uppercase, take effect on all screen sizes, while prefixed utilities, such as md:uppercase
, only take effect at the specified breakpoint and above.
Here are some benefits of Tailwind CSS for responsive design:
md:padding-4
.Responsive is crucial because of the following reasons:
Tailwind CSS breakpoints are viewport sizes that change your website's or application's layout to adapt to different screen sizes. They are represented as prefixes to utility classes, such as sm
, md
, lg
, xl
, and 2xl
, which correspond to different minimum widths.
By default, Tailwind uses a mobile-first breakpoint system, where unprefixed utilities take effect on all screen sizes, and prefixed utilities only take effect at the specified breakpoint and above.
For example, to underline text on screens 640px
and wider, you can use sm:underline
.
There are five breakpoints by default, inspired by common device resolutions in TailwindCSS:
640 pixels,
typically associated with mobile devices and small screens768 pixels,
commonly used for tablets and devices with larger screens1024 pixels
, covers desktop and laptop screens1280 pixels
, suitable for larger screens, such as high-resolution desktop displays1536 pixels
These breakpoints can be customized in the tailwind.config.js
file. By default, Tailwind looks for an optional tailwind.config.js
file at the root of your project where you can define any customizations.
The code below demonstrates a customized Tailwind project:
1/** @type {import('tailwindcss').Config} */
2module.exports = {
3 content: ['./src/**/*.{html,js}'],
4 theme: {
5 screens: {
6 xs: "320px",
7 ss: "480px",
8 sm: "769px",
9 md: "900px",
10 lg: "1025px",
11 xl: "1200px",
12 xxl: "1700px",
13 }
14 },
15}
This code snippet configuration above overrides the default Tailwind configuration and sets custom breakpoints named xs
(extra small), ss
(small mobile), sm
(tablet), md
(medium), lg
(large), xl
(extra large), and xxl
(extra, extra large) at specific pixel widths.
Media queries have long allowed web developers to create responsive frontend design by changing element styling based on viewport size. But changing styling based on a container's size, rather than the entire viewport, has not been possible until now.
Tailwind CSS's new container queries unlock this capability. The syntax is similar to media queries, but container queries require defining both the container to watch and the styles to change when it resizes. This opens up new possibilities for responsive components that dynamically adapt their layout based on their container's available space.
As of November 2022, major web browsers now support CSS container queries. With container queries, components can respond to their containers, not just the viewport. This granular control over responsiveness unlocks more robust, flexible, and scalable designs.
Source: Can I Use—CSS Container Queries (Size)
According to MDN:
Container queries enable you to apply styles to an element based on the size of the element's container.
If, for example, a container has less space available in the surrounding context, you can hide certain elements or use smaller fonts. Container queries are an alternative to media queries, which apply styles to elements based on viewport size or other device characteristics.
The @tailwindcss/container-queries
is a plugin for Tailwind CSS v3.2+ that provides utilities for container queries. The Tailwind CSS container queries allow you to style elements based on the width of their parent container, not just the viewport. It adds container query capabilities using a new @
syntax to differentiate it from regular media queries.
Source: MDN Docs
In the next section, I will walk you through how to get started with Tailwind container queries and also show you its usefulness using some demo examples. In the demo, I will show you how we will style elements based on the width of their containers. In the example, we will style a blockquote
differently depending on the size of its container.
Traditional media queries in CSS, while offering responsive design capabilities, come with their fair share of challenges for developers. Tailwind CSS Container Queries aims to tackle these issues and streamline the process.
One major pain point in front-end web development is CSS complexity. Media queries can lead to code duplication and inconsistencies as developers manage multiple styles for different screen sizes. Tailwind's container queries simplify this by allowing for more concise and declarative styling, promoting maintainability, and reducing the risk of errors.
Another challenge is in achieving truly responsive design. Media queries can be cumbersome when dealing with elements that need to adapt based on their container's size, like sidebars or nested components. Tailwind container queries offer a solution by enabling developers to target specific container elements and adjust styles accordingly, leading to more dynamic and flexible layouts.
Scalability is also a concern. As applications grow, managing media queries across a large codebase becomes difficult. Tailwind container queries promote a more modular approach, allowing developers to reason about styles within their components, making it easier to scale the application without worrying about CSS breaking down.
To install the plugin from npm, run the following command:
npm install @tailwindcss/container-queries
Then add the plugin to your tailwind.config.js
file like so:
1// tailwind.config.js
2module.exports = {
3 theme: {
4 // ...
5 },
6 plugins: [
7 require('@tailwindcss/container-queries'),
8 // ...
9 ],
10}
To use Tailwind container queries, you need to add the @container
class to the parent elements to mark them as containers. Then you can use @lg
and other variants to apply styles when that container exceeds those breakpoint widths.
The plugin includes default container breakpoints that match Tailwind's regular responsive breakpoint scale. So @lg
applies when the container width is larger than 768px
, @xl
for 1280px
, etc.
This allows styling elements based on parent container sizes rather than only viewport sizes like regular media queries.
The table below shows the different breakpoints for the Tailwind container queries:
Name | Value |
---|---|
xs | 20rem |
sm | 24rem |
md | 28rem |
lg | 32rem |
xl | 36rem |
2xl | 42rem |
3xl | 48rem |
4xl | 56rem |
5xl | 64rem |
6xl | 72rem |
7xl | 80rem |
To get started using container queries in Tailwind, the first step is marking an element as a container to watch using the @container
class in Tailwind CSS.
This sets that element as the parent to track for sizing changes. Then, container variants like @lg:
and @md:
can be used to apply styles when the container exceeds those breakpoint widths.
For example, @lg:text-center
would center the text when the container goes over the large breakpoint. The container variants correspond to the regular breakpoint values in Tailwind (see table above).
1<div class="@container">
2 <div class="block @lg:flex">
3 <!-- ... -->
4 </div>
5</div>
In the code snippet above, we declared our container div
element by passing the class @container
to it. Then, the next div
sets the display property to flex
once the parent element's width exceeds 32rem
.
So container queries rely on the @container
class to designate the parent element and then use variants to modify styling based on the container dimensions. This allows components to respond to their immediate parent size rather than only the whole viewport.
You can configure which values are available using the containers
key in your tailwind.config.js
file:
1// tailwind.config.js
2module.exports = {
3 theme: {
4 extend: {
5 containers: {
6 3xs: '12rem',
7 2xs: '16rem',
8 // etc...
9 },
10 },
11 },
12 plugins: [
13 require('@tailwindcss/container-queries'),
14 // ...
15 ],
16}
Tailwind CSS container query also comes with support for arbitrary values, using the @[...]
syntax:
1<div class="@container">
2 <div class="block @[712px]:flex">
3 <!-- ... -->
4 </div>
5</div>
In the code snippet above, we declared our container div
element by passing the class @container
to it. Then, the next div
sets the display property to flex
once the parent element's width exceeds 712px
.
In addition to generic containers, Tailwind CSS container queries allow you to create named containers using the @container/{name}
syntax.
For example:
1<div class="@container/header">
2 <!-- container content -->
3</div>
4
5<div class="@container/main">
6 <!-- container content -->
7</div>
This defines a container with the name header
and another named main
.
You can then target the named containers specifically using their name in the container query variants:
1<div class="@container/header">
2
3 <h1 class="@lg/header:text-2xl">
4 <!-- the headline will be sized based on the "header" container -->
5 </h1>
6
7</div>
8
9<div class="@container/main">
10
11 <p class="@lg/main:text-lg">
12 <!-- text will be sized based on the "main" container -->
13 </p>
14
15</div>
So @lg/header:text-2xl
will apply the text-2xl
utility only when the "header" container exceeds the large breakpoint. This allows you to create different responsive behaviors based on individual container widths, instead of everything responding to one global container.
Named containers enable finer control over responsive styling in complex layouts with multiple containers. You can make elements respond specifically to their intended parent container's available space.
For example, sidebars, headers, footers, and other components can each adapt independently of each other based on their named container's current width using container query variants.
In this section, I will walk you through an example of the implementation of @tailwindcss/container-queries
to style elements based on the width of the parent container.
We will be building this below:
Scenario: We have an image that needs to be displayed at full width on small screens (less than 640px
), but on medium and large screens (640px
and above) it should have a maximum width of 50%
.
Notice how in the GIF above, the image is scaled differently based on the width of the container.
1<img src="https://helene-ui.netlify.app/ui/chat-window/img/embedded-image.png" class="responsive-image">
1.responsive-image {
2 width: 100%;
3}
4
5@media (min-width: 640px) {
6 .responsive-image {
7 max-width: 50%;
8 }
9}
Start by adding Tailwind the container query plugin to your tailwind.config.js
like so:
1// tailwind.config.js
2
3/** @type {import('tailwindcss').Config} */
4module.exports = {
5 theme: {},
6 plugins: [require('@tailwindcss/container-queries')],
7}
HTML Structure::
1<div class="container">
2 <img src="https://helene-ui.netlify.app/ui/chat-window/img/embedded-image.png" class="responsive-image">
3</div>
Tailwind Classes:
1@container {
2 max-width: 640px; }
3
4.responsive-image {
5 width: 100%;
6}
7
8.container > .responsive-image { @md:max-width: 50%; }
What the above code snippet does:
container
class to the element containing the image.@container
rule sets the maximum width for the container element.container > .responsive-image
).@md
prefix applies the max-width: 50%
style only on medium screens and above (equivalent to the min-width: 640px
media query).Both approaches achieve the same responsive behavior for the image. Tailwind container queries offer a more concise and component-specific way to handle responsiveness based on parent container size.
See the full code for this article: https://play.tailwindcss.com/aWJdQDobmt?file=css
Through reading this article, you have learned how to use container queries in Tailwind CSS to build robust responsive web design or frontend designs.
You learned that traditional media queries have limitations when styling elements based on their parent container's dimensions. Container queries address this by allowing you to apply styling based on an element's immediate parent width.
You saw how to install and configure the Tailwind CSS container queries plugin. You can designate parent elements as containers with the @container
class, then use variants like @lg:
and @md:
to apply responsive styles based on container breakpoints.
You saw an example implementation of container queries to dynamically style quote blocks in different layouts based on the container width. This showcased the power of container queries over regular media queries.
If you wish to learn more about container queries, do check out these articles and documentation for a quick grasp of the topic:
Emmanuel is an experienced and enthusiastic software developer and technical writer with proven years of professional experience. He focuses on full-stack web development. He is fluent in React, TypeScript, VueJS, and NodeJS and familiar with industry-standard technologies such as version control, headless CMS, and JAMstack. He is passionate about knowledge sharing.