How to use container queries now

Trending 1 month ago

Philip Walton

Recently, Chris Coyier wrote a blog post posing nan question:

Now that instrumentality queries are supported successful each browser engines, why aren't much developers utilizing them?

Chris's station lists a number of imaginable reasons (for example, deficiency of awareness, aged habits dice hard), but there's 1 particular logic that stands out.

Some developers opportunity they want to usage instrumentality queries now but deliberation they can't because they still person to support older browsers.

As you whitethorn person guessed from nan title, we deliberation it's imaginable for astir developers to usage instrumentality queries now—in production—even if you person to support older browsers. This station walks you done nan attack we urge to do that.

A pragmatic approach

If you want to usage instrumentality queries successful your codification now, but you want nan acquisition to look nan aforesaid successful each browsers, you tin instrumentality a JavaScript-based fallback for browsers that don't support instrumentality queries.

The mobility past becomes: really broad should nan fallback be?

As pinch immoderate fallback, nan situation is to onslaught a bully equilibrium betwixt usefulness and performance. For CSS features, it's often intolerable to support nan afloat API (see why not usage a polyfill). However, you tin get beautiful acold by identifying nan halfway group of functionality that astir developers want to use, and past optimize nan fallback for conscionable those features.

But what is nan "core group of functionality" that astir developers want for instrumentality queries? To reply that question, see really astir developers build responsive sites presently pinch media queries.

Pretty overmuch each modern creation systems and constituent libraries person standardized connected mobile-first principles, implemented utilizing a group of predefined breakpoints (such arsenic SM, MD, LG, XL). Components are optimized to show good connected mini screens by default, and past styles are conditionally layered connected to support a fixed group of larger surface widths. (See nan Bootstrap and Tailwind archiving for examples of this.)

This attack is just arsenic applicable to container-based creation systems arsenic it is to viewport-based creation systems because, successful astir cases, what's applicable to designers is not really large nan surface aliases viewport is, it's really overmuch abstraction is disposable to nan constituent successful nan discourse that it's been placed. In different words, alternatively than breakpoints being comparative to nan full viewport (and applicable to nan full page), breakpoints would use to circumstantial contented areas, specified arsenic sidebars, modal dialogs, aliases station bodies.

If you're capable to activity wrong nan constraints of a mobile-first, breakpoint-based attack (which astir developers presently do), past implementing a container-based fallback for that attack is importantly easier than implementing afloat support for each azygous instrumentality query feature.

The adjacent conception explains precisely really this each works, on pinch a step-by-step guideline showing you really to instrumentality it connected an existing site.

How it works

Step 1: update your constituent styles to usage @container rules alternatively of @media rules

In this first step, place immoderate components connected your tract that you deliberation would use from container-based sizing alternatively than viewport-based sizing.

It's a bully thought to commencement pinch conscionable 1 aliases 2 components to spot really this strategy works, but if you want to person 100% of your components to container-based styling, that's good too! The awesome point astir this strategy is you tin adopt it incrementally if needed.

Once you've identified nan components you want to update, you'll request to alteration each @media norm successful those components' CSS to an @container rule.

Here's an illustration of really that mightiness look connected a .photo-gallery constituent that, by default, is simply a azygous column, and past uses @media rules to update its layout to go 2 and 3 columns successful nan MD and XL breakpoints (respectively):

.photo-gallery { display: grid; grid-template-columns: 1fr; } /* Styles for nan `MD` breakpoint */ @media (min-width: 800px) { .photo-gallery { grid-template-columns: 1fr 1fr; } } /* Styles for nan `XL` breakpoint */ @media (min-width: 1200px) { .photo-gallery { grid-template-columns: 1fr 1fr 1fr; } }

To update nan .photo-gallery constituent to usage @container rules, first switch nan drawstring @media pinch nan drawstring @container successful nan CSS. The grammar for these 2 rules is akin capable that, successful galore cases, this whitethorn beryllium each you request to change.

Depending connected nan creation of your site, you whitethorn besides request to update nan size condition, particularly if your site's @media rules are making definite assumptions astir really overmuch abstraction will beryllium disposable to circumstantial components astatine various viewport sizes.

For example, if nan styles for nan .photo-gallery CSS astatine nan MD and XL breakpoints successful erstwhile illustration presume that a 200 pixel-wide sidebar will beryllium displayed astatine those breakpoints, past nan size conditions for nan @container rules should beryllium astir 200 pixels less—assuming that nan "container" constituent for nan .photo-gallery constituent won't see nan sidebar.

Altogether, to person nan .photo-gallery CSS from @media rules to @container rules, nan afloat group of changes are arsenic follows:

/* Before, utilizing nan original breakpoint sizes: */ @media (min-width: 800px) { /* ... */ } @media (min-width: 1200px) { /* ... */ } /* After, pinch nan breakpoint sizes reduced by 200px: */ @container (min-width: 600px) { /* ... */ } @container (min-width: 1000px) { /* ... */ }

Note that you don't person to alteration immoderate of nan styles wrong nan declaration block, arsenic those bespeak how nan constituent looks alternatively than when circumstantial styles should apply.

Once you've updated your components styles from @media rules to @container rules, nan adjacent measurement is to configure your instrumentality elements.

Step 2: adhd instrumentality elements to your HTML

The erstwhile measurement defined constituent styles that are based connected nan size of a instrumentality element. The adjacent measurement is to specify which elements connected your page should beryllium those instrumentality elements whose size nan @container rules will beryllium comparative to.

You tin state immoderate constituent to beryllium a instrumentality constituent successful CSS by mounting its container-type spot to either size aliases inline-size. If your instrumentality rules are width-based, past inline-size is mostly what you want to use.

Consider a tract pinch nan pursuing basal HTML structure:

<body> <div class="sidebar">...</div> <div class="content">...</div> </body>

To make nan .sidebar and .content elements connected this tract containers, adhd this norm to your CSS:

.content, .sidebar { container-type: inline-size; }

For browsers that support instrumentality queries, this CSS is each you request to make nan constituent styles defined successful nan erstwhile measurement comparative to either nan main contented area aliases nan sidebar, depending connected which constituent they hap to beryllium within.

However, for browsers that don't support instrumentality queries, there's immoderate further activity to do.

You request to adhd immoderate codification that detects erstwhile nan size of nan instrumentality elements changes and past updates nan DOM based connected those changes successful a measurement that your CSS tin hook into.

Fortunately, nan codification required to do that is minimal, and it tin beryllium wholly abstracted distant into a shared constituent that you tin usage connected immoderate tract and successful immoderate contented area.

The pursuing codification defines a reusable <responsive-container> constituent that automatically listens for size changes and adds breakpoint classes that your CSS tin style based on:

// A mapping of default breakpoint people names and min-width sizes. // Redefine these (or adhd more) arsenic needed based connected your site's design. const defaultBreakpoints = {SM: 400, MD: 600 LG: 800, XL: 1000}; // A resize perceiver that monitors size changes to each <responsive-container> // elements and calls their `updateBreakpoints()` method pinch nan updated size. const ro = new ResizeObserver((entries) => { entries.forEach((e) => e.target.updateBreakpoints(e.contentRect)); }); class ResponsiveContainer extends HTMLElement { connectedCallback() { const bps = this.getAttribute('breakpoints'); this.breakpoints = bps ? JSON.parse(bps) : defaultBreakpoints; this.name = this.getAttribute('name') || ''; ro.observe(this); } disconnectedCallback() { ro.unobserve(this); } updateBreakpoints(contentRect) { for (const bp of Object.keys(this.breakpoints)) { const minWidth = this.breakpoints[bp]; const className = this.name ? `${this.name}-${bp}` : bp; this.classList.toggle(className, contentRect.width >= minWidth); } } } self.customElements.define('responsive-container', ResponsiveContainer);

This codification useful by creating a ResizeObserver that automatically listens for size changes to immoderate <responsive-container> elements successful nan DOM. If nan size alteration matches 1 of nan defined breakpoint sizes, past a people pinch that breakpoint sanction is added to nan constituent (and removed if nan information nary longer matches).

For example, if nan width of nan <responsive-container> constituent is betwixt 600 and 800 pixels (based connected nan default breakpoint values group successful nan code), past nan SM and MD classes will beryllium added, for illustration this:

<responsive-container class="SM MD">...</responsive-container>

These classes let you to specify fallback styles for browsers that don't support instrumentality queries (see step 3: adhd fallback styles to your CSS).

To update nan erstwhile HTML codification to usage this instrumentality element, alteration nan sidebar and main contented <div> elements to beryllium <responsive-container> elements instead:

<body> <responsive-container class="sidebar">...</responsive-container> <responsive-container class="content">...</responsive-container> </body>

In astir situations, you tin conscionable usage nan <responsive-container> constituent without immoderate customization, but if you do request to customize it, nan pursuing options are available:

  • Custom breakpoint sizes: This codification uses a group of default breakpoint people names and min-width sizes, but you alteration these defaults to beryllium immoderate you like. You tin besides override these values connected a per-element ground utilizing nan breakpoints attribute.
  • Named containers: This codification besides supports named containers by passing a sanction attribute. This tin beryllium important if you request to nest instrumentality elements. See nan limitations section for much details.

Here is an illustration that sets some of these configuration options:

<responsive-container name='sidebar' breakpoints='{"bp4":400,"bp5":500,"bp6":600,"bp7":700,"bp8":800,"bp9":900,"bp10":1000}'> </responsive-container>

Finally, erstwhile bundling this code, make judge you usage characteristic discovery and move import() to only load it if nan browser doesn't support instrumentality queries.

if (!CSS.supports('container-type: inline-size')) { import('./path/to/responsive-container.js'); }

Step 3: adhd fallback styles to your CSS

The past measurement successful this strategy is to adhd fallback styles for browsers that don't admit nan styles defined successful nan @container rules. Do this by duplicating those rules utilizing nan breakpoint classes that get group connected nan <responsive-container> elements.

Continuing pinch nan .photo-gallery illustration from before, nan fallback styles for nan 2 @container rules mightiness look for illustration this:

/* Container query styles for nan `MD` breakpoint. */ @container (min-width: 600px) { .photo-gallery { grid-template-columns: 1fr 1fr; } } /* Fallback styles for nan `MD` breakpoint. */ @supports not (container-type: inline-size) { :where(responsive-container.MD) .photo-gallery { grid-template-columns: 1fr 1fr; } } /* Container query styles for nan `XL` breakpoint. */ @container (min-width: 1000px) { .photo-gallery { grid-template-columns: 1fr 1fr 1fr; } } /* Fallback styles for nan `XL` breakpoint. */ @supports not (container-type: inline-size) { :where(responsive-container.XL) .photo-gallery { grid-template-columns: 1fr 1fr 1fr; } }

In this code, for each @container norm location is an balanced norm conditionally matching nan <responsive-container> constituent if nan corresponding breakpoint people is present.

The information of nan selector matching nan <responsive-container> constituent is wrapped successful a :where() functional pseudo-class selector, to support nan specificity of nan fallback selector balanced to nan specificity of nan original selector wrong nan @container rule.

Each fallback norm is besides wrapped successful an @supports declaration. While this is not strictly basal for nan fallback to work, it intends that nan browser wholly ignores these rules if it supports instrumentality queries, which tin amended style matching capacity successful general. It besides perchance allows build devices aliases CDNs to portion those declarations if they cognize nan browser supports instrumentality queries and doesn't request those fallback styles.

The main downside of this fallback strategy is it requires you to repetition style declaration twice, which is some tedious and correction prone. However, if you're utilizing a CSS preprocessor, you tin absurd that into a mixin that generates some nan @container norm and nan fallback codification for you. Here's an illustration utilizing Sass:

@use 'sass:map'; $breakpoints: ( 'SM': 400px, 'MD': 600px, 'LG': 800px, 'XL': 1000px, ); @mixin breakpoint($breakpoint) { @container (min-width: #{map.get($breakpoints, $breakpoint)}) { @content(); } @supports not (container-type: inline-size) { :where(responsive-container.#{$breakpoint}) & { @content(); } } }

Then, erstwhile you person this mixin, you could update nan original .photo-gallery constituent styles to thing for illustration this, which eliminates nan plagiarism entirely:

.photo-gallery { display: grid; grid-template-columns: 1fr; @include breakpoint('MD') { grid-template-columns: 1fr 1fr; } @include breakpoint('XL') { grid-template-columns: 1fr 1fr 1fr; } }

And that's each location is to it!

Recap

So, to recap, here's really to update your codification to usage instrumentality queries now pinch a transverse browser fallback.

  1. Identity components that you want to style comparative to their container, and update nan @media rules successful their CSS to usage @container rules. Also (if you're not already), standardize connected a group of breakpoint names to lucifer nan size conditions successful your instrumentality rules.
  2. Add nan JavaScript that powers nan civilization <responsive-container> element, and past adhd nan <responsive-container> constituent to immoderate contented areas successful your page that you want your components to beryllium comparative to.
  3. To support older browsers, adhd fallback styles to your CSS that lucifer against nan breakpoint classes that get automatically added to nan <responsive-container> elements successful your HTML. Ideally usage a CSS preprocessor mixin to debar having to constitute nan aforesaid styles twice.

The awesome point astir this strategy is location is simply a one-time setup cost, but aft that it doesn't return immoderate further effort to adhd caller components and specify container-relative styles for them.

Seeing it successful action

Probably nan champion measurement to understand really each these steps fresh together is to spot a demo of it successful action.

A video of a personification interacting pinch nan instrumentality queries demo site. The personification is resizing nan contented areas to show really nan constituent styles update based connected nan size of their containing contented area.

This demo is an updated type of a tract created successful 2019 (before instrumentality queries existed) to thief exemplify why instrumentality queries are basal to building genuinely responsive constituent libraries.

Since this tract already had styles defined for a bunch of "responsive components", it was a cleanable campaigner to trial retired nan strategy introduced present connected a non-trivial site. Turns out, it was really rather elemental to update and required almost nary changes to nan original tract styles.

You tin cheque retired nan full demo root code connected GitHub, and beryllium judge to look specifically astatine nan demo constituent CSS, to spot really nan fallback styles are defined. If you want to trial retired conscionable nan fallback behavior, there's a fallback-only demo that includes conscionable that variant—even successful browsers that support instrumentality queries.

Limitations and imaginable improvements

As mentioned astatine nan opening of this post, nan strategy outlined present useful good for nan mostly of usage cases that developers really attraction astir erstwhile reaching for instrumentality queries.

That said, location are immoderate much precocious usage cases that this strategy intentionally does not effort to support, addressed next:

Container query units

The specification for instrumentality queries defines a number of new units, that are each comparative to nan container's size. While perchance useful successful immoderate cases, nan mostly of responsive designs tin apt beryllium achieved done existing means, specified arsenic percentages aliases utilizing grid aliases flex layouts.

That said, if you do request to usage instrumentality query units, you could easy adhd support for them utilizing custom properties. Specifically, by defining a civilization spot for each portion utilized connected nan instrumentality element, for illustration this:

responsive-container { --cqw: 1cqw; --cqh: 1cqh; }

And past whenever you request to entree nan instrumentality query units, usage those properties, alternatively than utilizing nan portion itself:

.photo-gallery { font-size: calc(10 * var(--cqw)); }

Then, to support older browsers, group nan values for those civilization properties connected nan instrumentality constituent wrong nan ResizeObserver callback.

class ResponsiveContainer extends HTMLElement { // ... updateBreakpoints(contentRect) { this.style.setProperty('--cqw', `${contentRect.width / 100}px`); this.style.setProperty('--cqh', `${contentRect.height / 100}px`); // ... } }

This efficaciously lets you "pass" those values from JavaScript to CSS, and past you person nan afloat powerfulness of CSS (for example, calc(), min(), max(), clamp()) to manipulate them arsenic needed.

Logical properties and penning mode support

You whitethorn person noticed nan usage of inline-size alternatively than width successful nan @container declarations successful immoderate of these CSS examples. You whitethorn person besides noticed nan caller cqi and cqb units (for inline and artifact sizes, respectively). These caller features bespeak CSS's displacement to logical properties and values alternatively than beingness aliases directional ones.

Unfortunately, APIs for illustration Resize Observer still study values successful width and height, truthful if your designs request nan elasticity of logical properties, past you request to fig that retired for yourself.

While it's imaginable to get nan penning mode utilizing thing for illustration getComputedStyle() passing successful nan instrumentality element, doing truthful has a cost, and there's not really a bully measurement to observe if nan penning mode changes.

For this reason, nan champion attack is for nan <responsive-container> constituent itself to judge a penning mode spot that nan tract proprietor tin group (and update) arsenic needed. To instrumentality this, you'd travel nan aforesaid attack shown successful nan erstwhile section, and switch width and tallness arsenic needed.

Nested containers

The container-name spot lets you springiness a instrumentality a name, which you tin past reference successful an @container rule. Named containers are useful if you person containers nested wrong containers and you request definite rules to only lucifer definite containers (not conscionable nan nearest ancestor container).

The fallback strategy outlined present uses nan descendant combinator to style elements matching definite breakpoint classes. This tin break if you person nested containers, since immoderate number of breakpoint classes from aggregate instrumentality constituent ancestors could lucifer a fixed constituent astatine nan aforesaid time.

For example, present location are 2 <responsive-container> elements wrapping nan .photo-gallery component, but since nan outer instrumentality is larger than nan soul container, they person different breakpoint classes added.

<responsive-container class="SM MD LG"> ... <responsive-container class="SM"> ... <div class="photo-gallery">...</div class="photo-gallery"> </responsive-container> </responsive-container>

In this example, nan MD and LG people connected nan outer instrumentality would impact nan style rules matching nan .photo-gallery component, which doesn't lucifer nan behaviour of instrumentality queries (since they only lucifer against nan nearest ancestor container).

To woody pinch this, either:

  1. Make judge you ever sanction immoderate containers that you're nesting, and past guarantee your breakpoint classes are prefixed pinch that instrumentality sanction to debar clashes.
  2. Use nan child combinator alternatively of nan descendant combinator successful your fallback selectors (which is simply a spot much limiting).

The nested containers conception of nan demo tract has an illustration of this moving utilizing named containers, on pinch nan Sass mixin it uses successful nan codification to make nan fallback styles for some named and unnamed @container rules.

What astir browsers that don't support :where(), Custom Elements, aliases Resize Observer?

While these APIs whitethorn look comparatively new, they've each been supported successful each browsers for much than 3 years, and they're each portion of Baseline wide available.

So unless you person information showing that a important information of your site's visitors are connected browsers that don't support 1 of these features, past location is nary logic not to freely usage them without a fallback.

Even then, for this circumstantial usage case, nan worst that could hap is nan fallback won't activity for a very mini percent of your users, which intends they'll spot nan default position alternatively than a position optimized for nan instrumentality size.

The functionality of nan tract should still work, and that's what really matters.

Why not conscionable usage a instrumentality query polyfill?

CSS features are notoriously difficult to polyfill, and mostly require re-implementing nan brower's full CSS parser and cascade logic successful JavaScript. As a result, CSS polyfill authors person to make galore tradeoffs that almost ever travel pinch galore characteristic limitations arsenic good arsenic important capacity overhead.

For these reasons, we mostly don't urge utilizing CSS polyfills successful production, including nan container-query-polyfill from Google Chrome Labs, which is nary longer maintained (and was chiefly intended for demo purposes).

The fallback strategy discussed present has less limitations, requires acold little code, and will execute importantly amended than immoderate instrumentality query polyfill ever could.

Do you moreover request to instrumentality a fallback for older browsers?

If you are concerned astir immoderate of nan limitations mentioned here, it's astir apt worthy asking yourself whether you really request to instrumentality a fallback successful nan first place. After all, nan easiest measurement to debar these limitations is to conscionable usage nan characteristic without immoderate fallbacks. Honestly, successful galore cases, that whitethorn beryllium a perfectly reasonable choice.

According to caniuse.com, instrumentality queries are supported by 90% of world net users, and for galore group reference this post, nan number is apt rather a spot higher for their personification base. So it's important to support successful mind that most of your users will spot nan container-query type of your UI. And for nan 10% of users that won't, it's not for illustration they're going to person a surgery experience. When pursuing this strategy, successful nan worst lawsuit these users will spot nan default aliases "mobile" layout for immoderate components, which is not nan extremity of nan world.

When making tradeoffs, it's a bully believe to optimize for nan mostly of your users—rather than defaulting to a lowest-common-denominator attack that gives each users a consistent, but sub-par, experience.

So earlier you presume that you can't usage instrumentality queries owed to deficiency of browser support, really return nan clip to see what nan acquisition would beryllium for illustration if you did take to adopt them. The tradeoff whitethorn beryllium good worthy it, moreover without immoderate fallbacks.

Looking forward

Hopefully this station has convinced you that it is imaginable to usage instrumentality queries successful accumulation now, and that you don't person to hold for years until each non-supporting browsers wholly disappear.

While nan strategy outlined present does require a spot of other work, it should beryllium elemental and straightforward capable that astir group tin adopt it connected their sites. That said, location is surely room to make it moreover easier to adopt. One thought would beryllium to consolidate a batch of nan disparate parts into a azygous component—optimized for a circumstantial model aliases stack—that handles each of nan glue activity for you. If you build thing for illustration this, fto america cognize and we tin thief beforehand it!

Lastly, beyond instrumentality queries, location are truthful galore astonishing CSS and UI features that are now interoperable crossed each awesome browser engines. As a community, let's fig retired really we tin really usage those features now, truthful our users tin benefit.


Update (July 25, 2024): primitively nan guidance successful "Step 1" suggested that media queries and instrumentality queries could usage nan aforesaid size conditions. This is often existent but not ever (as immoderate reasons rightly pointed out). The updated guidance now clarifies this and offers illustration cases wherever nan size conditions mightiness request to change.

Update (July 2, 2024): primitively each of nan CSS codification examples utilized Sass (for consistency pinch nan last recommendation). Based connected feedback from readers, nan first fewer CSS person been updated to plain CSS, and Sass is only utilized successful nan codification samples that require nan usage of mixins.

More
Source Web Development
Web Development