Sunday, June 30, 2024
HomeCSSCSS Fashion Queries

CSS Fashion Queries


For me, 2022 is the very best 12 months ever for CSS. We acquired plenty of new stuff supported in secure browsers and it’s similar to dwelling a dream. From CSS subgrid, :has selector, container queries, and the brand new viewport models. So many issues to understand, I perceive – however I’m positive we agree that that is thrilling, isn’t it?

Just lately, the Chrome staff launched experimental assist for a brand new proposed CSS spec, type queries. Briefly, they allow us to question the type of a container, somewhat than the scale solely. This may be useful in circumstances the place querying the container dimension isn’t sufficient.

Let’s dig in.

Container dimension queries

Earlier than going into the main points of fashion queries, I want to have a fast reminder of container dimension queries first. As an alternative of counting on the viewport dimension to vary the type of a element, we are able to merely question towards the container dimension as an alternative.

Let’s check out an instance.

.o-grid__item {
  container-type: inline-size;
}

.c-article {
  
}

@container (min-width: 400px) {
  .c-article {
    
  }
}

First, we have to outline container-type on the container itself. Then, we are able to use @container and begin querying. As soon as that situation is met, the CSS will apply to the element inside that container.

Introducing type queries

In easy phrases, type queries allow us to question a CSS property or CSS variable for a container.

Fashion queries are nonetheless experimental and at present are carried out solely in Chrome Canary. To check them, go to chrome://flags and activate the “Experimental Internet Platform options” toggle.

As an example, we are able to verify if the container has show: flex and magnificence the kid primarily based on that.

.page-header {
  show: flex;
}

@container type(show: flex) {
  .page-header__start {
    flex: 1;
    show: flex;
    align-items: middle;
    border-right: 1px strong lightgrey;
  }
}

Ideally, the above ought to work, however the present type queries prototype in Chrome Canary is restricted to CSS variables solely. Fashion queries are anticipated to ship in Chrome M111.

For now, we are able to verify if the variable --boxed: true is added to the container and if sure, we are able to change the kid ingredient type primarily based on that.

Take into account the next determine.

Discover that the primary distinction between container queries and magnificence queries is that the primary question is for the scale and the latter question is for the type.

.card-container {
  --boxed: true;
}

@container type(--boxed: true) {
  .card {
    
  }
}

The issue

Earlier than diving into the place we are able to use type queries, I need to emphasize the query: what do type queries clear up? Aren’t dimension queries sufficient already?

That’s an excellent query to start out with. In dimension queries, we are able to management the styling of a element primarily based on its father or mother width, and that’s very helpful. In some circumstances, we would not want to question the scale in any respect. As an alternative, we need to question the computed type of a container.

To present you a greater thought, let’s have a look at the next determine.

That is an article physique that’s coming from a CMS. We now have a default type for the determine and one other type that appears featured.

Right here is the HTML markup.

<determine>
  <img src="cheesecake.jpg" alt="" />
  <figcaption>....</figcaption>
</determine>
figcaption {
  font-size: 13px;
  padding: 4px 8px;
  background: lightgrey;
}

After we begin styling the featured one, we have to override the above and have a CSS class that we are able to type with.

.featured-figure {
  show: flex;
  flex-wrap: wrap;
}

.featured-figure figcaption {
  font-size: 16px;
  padding: 16px;
  border-left: 3px strong;
  margin-left: -6rem;
  align-self: middle;
}

Cool, that works. Can we do higher? Sure! With type queries, we are able to add show: flex or a CSS variable --featured: true to the determine, and magnificence primarily based on that.

<determine>
  <img src="cheesecake.jpg" alt="" />
  <figcaption>....</figcaption>
</determine>
determine {
  container-name: determine;
  --featured: true;
}


@container determine type(--featured: true) {
  img {
    
  }

  figcaption {
    
  }
}

And if --featured: true isn’t there, we’ll default to the bottom determine design. We are able to use the not key phrase to verify when the determine doesn’t have show: flex.


@container determine not type(--featured: true) {
  figcaption {
    
  }
}

A couple of particulars to know

Each ingredient is a mode container by default

So there is no such thing as a must outline a mode container in any respect. It’s there for you by default.

Can’t we clear up that with a category title?

Sure, we are able to. The purpose of fashion queries is to make CSS extra readable and simpler to switch. The above logic might be written as one element CSS with out including all these kinds to a conditional class.

Demo

Much less CSS specificity points

What I like about utilizing type queries is that it’ll cut back CSS specificity as a result of we’ll rely much less on CSS variation courses or HTML knowledge attributes to type a element variation.

Within the following CSS, now we have a primary styling for a piece. Nothing fancy.

.part {
  background-color: lightgrey;
}

.section__title,
.section__desc {
  shade: #222;
}

We’d like a option to have a unique theme for it, so we used a variation class.

.section--dark {
  background-color: #222;
}

.section--dark .section__title,
.section--dark .section__desc {
  shade: #fff;
}

With type queries, we are able to use a container across the .part element, after which we tag the title and outline with out creating extra specificity in CSS.

@container type(--theme: darkish) {
  .part {
    background-color: #222;
  }

  .section__title,
  .section__desc {
    shade: #fff;
  }
}

That appears a lot cleaner to me.

Let’s discover a couple of use circumstances the place type queries might be useful.

Use circumstances & examples

Context-based styling

It is a frequent use case the place now we have the identical element used in a different way in the identical wrapper. Within the apart, now we have an article element that may embody a quantity or not.

At present, we would use a brand new CSS class to deal with the styling, or perhaps a variation class on the article element itself.

.most-popular {
  counter-reset: checklist;
}

.most-popular article {
  
}

Or we would use knowledge attributes within the HTML.

.most-popular[data-counter="true"] {
  counter-reset: checklist;
}

.most-popular[data-counter="true"] .article {
  
}

With CSS type queries, we are able to add a CSS variable to the father or mother ingredient, and magnificence the article accordingly. Have a look at that:

.most-popular {
  --counter: true;
}

@container type(--counter: true) {
  .articles-list {
    counter-reset: checklist;
  }

  .article {
    show: flex;
    align-items: flex-start;
  }

  .article:earlier than {
    counter-increment: checklist;
    content material: counter(checklist);
  }
}

We don’t even must have a variation class on the article element. CSS nesting isn’t wanted, too.

Demo

Element-level theme switching

Some parts we constructed want a unique theme primarily based on particular circumstances. Within the following instance, now we have a dashboard with totally different stats parts.

Primarily based on the wrapper, we have to swap the theme of the element.

At present, we are able to type the customized stats element primarily based on their container with a particular class.

.special-wrapper .stat {
  background-color: #122c46;
}

.special-wrapper .stat__icon {
  background-color: #2e547a;
}

.special-wrapper .stat__title {
  background-color: #b3cde7;
}

The above isn’t flawed or dangerous in any respect, however it will increase the specificity as a result of we nested the CSS. Let’s discover how we are able to implement the above with type queries.

First, we have to outline a toggle on the particular wrapper. Then, we are able to verify if that toggle is lively, and magnificence the stat element accordingly.

.special-wrapper {
  --theme: darkish;
  container-name: stats;
}

@container stats type(--theme: darkish) {
  .stat {
    
  }
}

What’s helpful about type queries in that context is that it’ll make sense to have the above type in a single place within the CSS.


.stat {
  
}

@container stats type(--theme: darkish) {
  .stat {
    
  }
}

Article element

Measurement container queries are so highly effective, they supplied us with a option to question a element towards its container. Right here is a well-liked instance from my article on container queries.

In CSS, we have to outline a dimension container, after which question the article element primarily based on that.

.o-grid__item {
  container-type: inline-size;
}

.c-article {
  
}


@container (min-width: 400px) {
  .c-article {
    show: flex;
    flex-wrap: wrap;
  }
}

And the featured or hero type.


@container (min-width: 700px) {
  .c-article {
    show: flex;
    justify-content: middle;
    align-items: middle;
    min-height: 350px;
  }

  .card__thumb {
    place: absolute;
    inset: 0;
    object-fit: cowl;
  }
}

That’s very helpful. The place type queries will help us? That’s an excellent query. In some circumstances, we is perhaps solely in making use of one type primarily based on the container dimension, and different kinds is perhaps conditional, or as per our want.

That is the place type queries turn into useful. We are able to mix a dimension and magnificence question for that function.

Take into account the next CSS.

.o-grid__item {
  container-type: inline-size;
  --horizontal: true;
}

@container (min-width: 400px) and type(--horizontal: true) {
  
}

That means, the horizontal type will solely work if the --horizontal variable is about to true on the container. You may title the variable and the worth as you want, for instance --horizontal: please.

Within the determine, the container dimension is identical, however what differentiates them is that the one on the correct has --horizontal: true

Demo

Group of avatars

On this instance, now we have a gaggle of person avatars. We have to lay them out in a different way primarily based on a CSS variable that’s set on the father or mother. I picked that instance from the Atlassian design system.

Take into account the next determine.

<div class="avatars-wrapper">
  <div class="avatars-list">
    <div class="avatar"></div>
    
  </div>
</div>

In CSS, I added a reputation to the container and outlined the --appearance: default variable;

.avatars-wrapper {
  container-name: avatars;
}

.avatars-list {
  show: flex;
  flex-wrap: wrap;
  hole: 0.25rem;
}

With that, we are able to use type queries to vary the structure primarily based on the --appearance variable.

@container avatars type(--appearance: stack) {
  .avatar {
    box-shadow: 0 0 0 2px #fff;
  }

  .avatar + .avatar {
    margin-inline-start: -0.5rem;
  }
}

@container avatars type(--appearance: grid) {
  .avatars-list {
    hole: 0.5rem;
    max-width: 200px;
  }
}

I think about this type of logic inside a design system. So useful and clear (my opinion, simply saying).

Demo

Conditional ornamental kinds

In some eventualities, we would want so as to add a conditional ornamental type to textual content components, primarily based on the place they’re within the HTML.

Take into account the next determine:

The heading and paragraph have a rotated background impact beneath them. That is accomplished through a pseudo-element.

<div class="content material">
  <h2></h2>
  <p></p>
</div>

To type them, we are able to use a CSS variable and verify if it’s toggled or not, and add the kinds accordingly. Within the instance, the :after pseudo-element is added to each baby of the .content material container.

.content material {
  --decorated: true;
}

@container type(--decorated: true) {
  :after {
    content material: "";
    place: absolute;
    inset: 0;
    background-color: var(--dec-color, inexperienced);
    opacity: 0.1;
    z-index: -1;
    remodel: rotate(-1.5deg);
  }
}

Demo

RTL styling: Card element

When writing RTL kinds, step one is so as to add dir=rtl to the <html> ingredient. As soon as that’s added, the course CSS property for each ingredient will turn into course: rtl.

With the rise of logical properties, we don’t must do a whole rewrite of the CSS. Take into account the next instance:

.merchandise {
  margin-inline-start: 1rem;
}

For left-to-right layouts, the above will compute to margin-left. And for right-to-left layouts, will probably be margin-right. Cool, proper? However we nonetheless don’t have the logical CSS that may verify a gradient course.

Fashion queries can turn into helpful for that downside. Take into account the next instance:

We now have a element that consists of two components, each of which ought to change course primarily based on the doc:

  • The gradient: it’s going from left to proper for LTR layouts.
  • Arrow course: it’s pointing to the correct.

The above can’t be managed with logical CSS. At present, we do one thing like this:

html[dir="rtl"] .card {
  background: linear-gradient(to left, ...);
}

html[dir="rtl"] .card__cta {
  remodel: scaleX(-1);
}

With type queries, we are able to question the container and verify if the course is the same as rtl, and alter the kinds accordingly.

.card {
  --bg-angle: to proper;
  background: linear-gradient(var(--bg-angle), #5521c3, #5893eb);
}

@container card type(course: rtl) {
  .card {
    --bg-angle: to left;
  }

  .card__cta {
    remodel: scaleX(-1);
  }
}

Please remember the fact that the present prototype of fashion queries doesn’t assist CSS properties inside the type() question. In consequence, I used a CSS variable in my demo as an alternative.

I wrote an in-depth information about RTL styling in CSS, in case you have an interest.

Demo

Information modules

What makes me enthusiastic about exploring this use case is that it’s an actual downside that I noticed on bbc.com. Initially, now we have the next information element.

Primarily based on its container, the styling ought to change a bit. Take into account the next determine:

Discover how the element now has two modifications:

  • A white background.
  • The title and outline container are padded from all sides.

Right here is how the CSS appears on BBC.com.

.media--padded {
  background: #fff;
}

.media--padded .media__content {
  padding: 0.75rem 0.75rem 3rem 0.75rem;
}

How we are able to clear up that through type queries? Merely, we’d like a option to inform the element that in case you dwell inside this container, the cardboard type must be padded.

.special-container {
  --card--padded: true;
}

@container type (--card-padded: true) {
  .media {
    background: #fff;
  }

  .media__content {
    padding: 0.75rem 0.75rem 3rem 0.75rem;
  }
}

From the identical web site, I noticed one other potential use case. See the next determine:

There are two variations:

  • Textual content shade is white.
  • The information element content material is padded.

The present CSS appears like this:

.module--reel p {
  shade: white;
  font-size: 18px;
  margin-top: 10px;
  margin-bottom: 20px;
}

With type queries, it’s a unique story. No must duplicate any CSS. We simply must activate the CSS variables that we’d like.

.module--reel {
  
  --card--padded: true;
  --light-on-dark: true;
}

@container type (--card-padded: true) {
}

@container type (--light-on-dark: true) {
  p {
    shade: white;
    font-size: 18px;
    margin-top: 10px;
    margin-bottom: 20px;
  }
}

That’s neat, proper?

Debug mode

In Sass pre-processor, we used to have a mixin that we inject into any CSS element or web page, and it’ll add CSS define to all baby components.

@mixin debug {
  * {
    define: strong 1px purple;
  }
}

After which we are able to use the mixin like the next:

.some-element {
  @embody debug;
}

With type queries, we are able to use a CSS variable for that which permit us to debug any element we’d like.

@container type(--debug: true) {
  * {
    define: strong 1px purple;
  }
}

.site-header {
  --debug: true;
}

Demo

Block hyperlinks is the best way of forcing a hyperlink to fill its father or mother, even when the precise hyperlink is an easy title.

Take into account the next instance.

“The “Learn extra” hyperlink within the card element is clickable, however we are able to enhance the person expertise by making the complete father or mother ingredient clickable as effectively.”

The draw back of a block hyperlink is that the textual content received’t be selectable, and in case now we have different hyperlinks (e.g: creator title), it received’t work.

So why not toggle them primarily based on the cardboard container? That is the place type queries come in useful.

.card {
  place: relative;
  container-name: card;
  --block-link: true;
}

@container card type(--block-link: true) {
  a:after {
    content material: "";
    place: absolute;
    inset: 0;
    define: strong 2px;
  }
}

Helpful, isn’t it?

Demo

Obtain card

In my container queries lab, I printed an instance of a obtain card that modifications primarily based on the container dimension. With type queries, we are able to make it even higher.

For instance, I need to change the cardboard type if the utmost width is 220px and the --card: true variable is on the market.

.download-wrapper {
  
  container: obtain / inline-size;
  --card: true;
}

@container obtain type(--card: true) and (max-width: 220px) {
  .c-download {
    flex-direction: column;
    align-items: middle;
    text-align: middle;
  }

  svg {
    order: -1;
  }
}

Demo

Outro

It was good to work on this text. I take pleasure in this type of work the place there’s a new CSS function and my job is solely doing intensive analysis on how we are able to use it.

CSS type queries are a robust addition to CSS. I can’t wait to see what others from the net neighborhood will do with them, too. Oh, and I can also’t resist the urge to create a brand new listing in iShadeed lab for type queries. Keep tuned!

When you’ve got any suggestions or query, I’m on Mastodon on front-end.social/@shadeed9, and Twitter (@shadeed9) in case you’re nonetheless round.

Additional studying

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments