Friday, May 3, 2024
HomeProgrammingDigging Deeper Into Container Fashion Queries | CSS-Methods

Digging Deeper Into Container Fashion Queries | CSS-Methods


I wrote up some early ideas on container fashion queries a short while again. It’s nonetheless early days. They’re already outlined within the CSS Containment Module Stage 1 specification (presently in Editor’s Draft standing) however there’s nonetheless a few excellent discussions happening.

The fundamental concept is that we are able to outline a container after which apply types conditionally to its descendants primarily based on its computed styling.

@container <title>? <circumstances> {
  /* conditional types */
}

The perfect instance I’ve seen up to now is eradicating italics from one thing like <em>, <i>, and <q> when they’re utilized in a context the place content material is already italicized:

em, i, q {
  font-style: italic; /* default UA habits */
}

/* When the container's font-style is italic, take away italics from these components. */
@container fashion(font-style: italic) {
  em, i, q {
    font-style: regular;
  }
}

That’s the final concept. However should you didn’t understand it, Miriam Suzanne, who’s an editor of the spec, retains an ongoing and thorough set of private notes on container fashion queries that’s publicly out there. It was up to date the opposite day and I spent a while in there making an attempt to wrap my head round extra nuanced points of favor queries. It’s unofficial stuff, however I believed I’d jot down some issues that stood out to me. Who is aware of? Perhaps it’s stuff we are able to finally stay up for!

Each aspect is a method container

We don’t even have to explictly assign a container-name or container-type to outline a method container as a result of all the pieces is a method container by default.

So, you see that instance above that removes italics? Discover it doesn’t determine a container. It jumps proper to the question utilizing the fashion() operate. So, what container is being queried? It’s going to be the direct mum or dad of the weather receiving the utilized types. And if not that, then it’s the subsequent nearest relative container that takes priority.

I like that. It’s very CSS-y for the question to go looking up for a match, then proceed to bubble up till it finds an identical situation.

It was arduous for my little mind to grasp why we are able to get away with an implicit container primarily based on types however not a lot once we’re coping with dimensional queries, like measurement and inline-size. Miriam explains it properly:

Dimensional queries require css containment on the dimensions, format, and magnificence of the container to be able to stop format loops. Containment is an invasive factor to use broadly, so it was necessary that authors have cautious management over what components are (or should not) measurement containers.

Fashion-based queries don’t have the identical limitation. There may be already no means in CSS for descendant types to have an effect on the computed types of an ancestor. So no containment is required, and there aren’t any invasive or sudden side-effects in establishing a component as a fashion question container.

(Emphasis mine)

All of it comes all the way down to penalties — of which there are none so far as all the pieces being a method question container proper out of the field.

  • If a container is discovered: circumstances are resolved towards that container.
  • If a number of containers match: the closest relative container takes priority.
  • If no matches are discovered: unknown returned.

That’s the identical “forgiving” spirit as the remainder of CSS.

A container can assist each dimensional and magnificence queries

Let’s say we wish outline a method question with out an specific container-name:

@container fashion(font-style: italic) {
  em {
    font-style: regular;
  }
}

This works as a result of all components are fashion containers, irrespective of the container-type. That’s what permits us to implicitly question types and depend on the closest match. And that is completely tremendous since, once more, there aren’t any adversarial negative effects when establishing fashion containers.

We’ve got to make use of an specific container-type for dimensional queries, however not a lot for fashion queries since each aspect is a method question. That additionally means this container is each a method and dimensional question:

.card-container {
  container: card / inline-size; /* implictly a method question container as properly */
}

Excluding a container from being queried

Maybe we don’t desire a container to take part within the matching course of. That’s the place it is likely to be potential to set container-type: none on a component.

.some-element {
  container-type: none;
}

Specific fashion question containers provide extra management of what will get queried

If, say, we had been to write down a method question for padding , there is no such thing as a dependable method to decide the perfect matching container, no matter whether or not we’re working with an explicitly named container or the closest direct mum or dad. That’s as a result of padding shouldn’t be an inherited property.

So, in these situations, we ought to make use of container-name to explictly inform the browser which containers they will pull from. We are able to even give a container a number of specific names to make it match extra circumstances:

.card {
  container-name: card format theme;
}

Oh, and container-name accepts any variety of non-compulsory and reusable names for a container! That’s much more flexibility in terms of serving to the browser make a selection when trying to find matches.

.theme {
  container-name: theme;
}
.grid {
  container-name: format;
}
.card {
  container-name: card format theme;
}

I kind of surprise if that may even be thought of a “fallback” within the occasion that one container is handed over.

Fashion queries might be mixed

The or and and operators enable us to mix wueries to maintain issues DRY:

@container bubble fashion(--arrow-position: begin begin) or fashion(--arrow-position: finish begin) {
  .bubble::after {
    border-block-end-color: inherit;
    inset-block-end: 100%;
  }
}

/* is similar as... */
@container bubble fashion(--arrow-position: begin begin) {
  /* and so forth. */
}
@container bubble fashion(--arrow-position: finish begin) {
  /* and so forth. */
}

Toggling types

There’s a bit overlap between container fashion queries and work being carried out to outline a toggle() operate. For instance, we are able to cycle by two font-style values, say italic and regular:

em, i, q {
  font-style: italic;
}

@container fashion(font-style: italic) {
  em, i, q {
    font-style: regular;
  }
}

Cool. However the proposal for CSS Toggles means that the toggle() operate can be an easier strategy:

em, i, q {
  font-style: toggle(italic, regular);
}

However something past this kind of binary use case is the place toggle() is much less appropriate. Fashion queries, although, are good to go. Miriam identifies three situations the place fashion queries are extra appropriate than a toggle():

/* When font-style is italic, apply background colour. */
/* Toggles can solely deal with one property at a time. */
@container fashion(font-style: italic) {
  em, i, q {
    background: lightpink;
  }
}

/* When font-style is italic and --color-mode equals gentle */
/* Toggles can solely consider one situation at a time */
@container fashion((font-style: italic) and (--color-mode: gentle)) {
  em, i, q {
    background: lightpink;
  }
}

/* Apply the identical question situation to a number of properties */
/* Toggles should set every one individually as separate toggles */
@container fashion(font-style: italic) {
  em, i, q {
    /* clipped gradient textual content */
    background: var(--feature-gradient);
    background-clip: textual content;
    box-decoration-break: clone;
    colour: clear;
    text-shadow: none;
  }
}

Fashion queries resolve the “Customized Property Toggle Hack”

Discover that fashion queries are a proper resolution for the “CSS customized property toggle trick”. In there, we set an empty customized property (--foo: ;) and use the comma-separated fallback methodology to “toggle” properties on and off when then customized property is about to an actual worth.

button {
  --is-raised: ; /* off by default */
  
  border: 1px stable var(--is-raised, rgb(0 0 0 / 0.1));
  box-shadow: var(
    --is-raised,
    0 1px hsl(0 0% 100% / 0.8) inset,
    0 0.1em 0.1em -0.1em rgb(0 0 0 / 0.2)
  );
  text-shadow: var(--is-raised, 0 -1px 1px rgb(0 0 0 / 0.3));
}

button:energetic {
  box-shadow: var(--is-raised, 0 1px 0.2em black inset);
}

#foo {
  --is-raised: preliminary; /* turned on, all fallbacks take impact. */
}

That’s tremendous cool, additionally numerous work that fashion container queries makes trivial.

Fashion queries and CSS generated content material

For generated content material produced by the content material property of ::earlier than and ::after pseudo-elements, the matching container is the aspect on which the content material is generated.

.bubble {
  --arrow-position: finish finish;
  container: bubble;
  border: medium stable inexperienced;
  place: relative;
}

.bubble::after {
  content material: "";
  border: 1em stable clear;
  place: absolute;
}

@container bubble fashion(--arrow-position: finish finish) {
  .bubble::after {
    border-block-start-color: inherit;
    inset-block-start: 100%;
    inset-inline-end: 1em;
  }
}

Fashion queries and net parts

We are able to outline an online element as a container and question it by fashion. First, we have now the <template> of the element:

<template id="media-host">
  <article>
    <div half="img">
      <slot title="img">…</slot>
    </div>
    <div half="content material">
      <slot title="title">…</slot>
      <slot title="content material">…</slot>
    </div>
  </article>
</template>

Then we use the :host pseudo-element as a container to set a container-name, a container-type, and a few high-level attributes on it:

:host {
  container: media-host / inline-size;
  --media-location: earlier than;
  --media-style: sq.;
  --theme: gentle;
}

Components contained in the <media-host> can question the parameters of the <media-host> aspect:

@container media-host fashion(--media-style: spherical) {
  [part="img"] {
    border-radius: 100%;
  }
}

What’s subsequent?

Once more, all of the stuff I’ve jotted down right here is predicated on Miriam’s notes, and people notes should not an alternative choice to the official spec. However they’re a sign of what’s being mentioned and the place issues may land sooner or later. I recognize Miriam linked up a handful of excellent discussions nonetheless happening that we are able to observe to remain up to the mark:

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments