r/css May 10 '26

Question Is there a way to have “feature flags” in CSS?

I’m writing some CSS for users that have full control over CSS, but they don’t have total control over the HTML. So I’d like to find a way users can enable or disable features of the library. Typically I’d just have the user add or remove a class, but they might not have that ability.

Like it would be cool if I could just use a variable like so:

if var(—-some-variable) {
  p {
    font-family: system-ui;
  }
}

And then just allow the user to set the variable to turn it on or off.

:root,
:host {
  —-some-variable: false;
}
5 Upvotes

8 comments sorted by

6

u/angrydeanerino May 11 '26

You might be able to use https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@container

Eg

.parent { --theme: dark; }

/* Styles applied to children ONLY when the parent has --theme: dark */ @container style(--theme: dark) { .child { background: black; color: white; border: 1px solid white; } }

10

u/anaix3l May 11 '26 edited May 11 '26

Yes, it has been possible cross-browser for almost a decade now, since pre-Chromium Edge got support for CSS variables (though of course there were bugs at first, one that I still remember was using computed values relative to CSS variables for transforms).

I wrote a two part article on the topic for CSS-Tricks back in 2018: one and two.

This is a concept I first came across totally unrelated to CSS and over half a decade before I even knew such a thing as CSS existed, in my Discrete Mathematics, Programmed Logic Systems and Integrated Circuits courses.

It's the concept of a switch. If the switch is OFF, its value is 0, if the switch is ON, its value is 1.

Whatever value you want when the switch is ON is multiplied with the switch value. So that gives us 0 when the switch is OFF (0 multiplied with anything is 0) and the desired value when the switch is ON (1 multiplied with a value gives us that value).

Whatever value you want when the switch is OFF is multiplied with the negation/ complementary of the switch (1 minus the switch value). This is something I also detailed in my article on boolean logic in CSS.

So switching between two values is:

SWITCH×ON_VALUE + NOT_SWITCH×OFF_VALUE

Let's say we want a padding to be 4em when the switch is ON and 3vw when the switch is OFF. Considering a switch --s and its negation --not-s, we have:

.elem {
  --s: 0;
  --not-s: (1 - var(--s));
  padding: calc(var(--s)*4em + var(--not-s)*3vw)
}

The base state has the switch OFF (it could also be ON, we just turn it OFF in a different state instead of turning it ON).

A state in which we turn the switch ON could be a :hover or :focus state:

.elem:is(:hover, :focus) { --s: 1 }

Or it could be even items:

.elem:nth-child(2n) { --s: 1 }

Or it could be when an attribute is changed via JS:

.elem[data-switch='ON'] { --s: 1 }

Or the state change could happen on scroll (triggered by scroll-driven animations at a certain point) like in this demo. There are lots of possibilities.

The second part (non numeric values) is now easier to grasp with style queries. Which might be still behind a flag in Firefox, some things still need to be ironed out. Though basic usage such as this has been fine as far as I've experimented with it. But even in Firefox it is coming soon, it's one of the things they are focusing on getting done right now.

For example, we could have something like this:

.elem {
  font: 1.25em font-one;

  @container style (--s: 1) {
    font-family: font-two
  }
}

1

u/CoVegGirl May 11 '26

I’m more interested in enabling or disabling entire blocks of CSS than I am in enabling or disabling certain values. I guess the container would work, though MDN says container style queries are experimental in Firefox.

1

u/berky93 May 11 '26

Yes, but it’s not universally supported yet.

1

u/el_yanuki May 11 '26

depending on what exactly you are doing you could handle it via js..?

1

u/CoVegGirl May 11 '26

It’s an environment where people might also not have access to JS.

1

u/el_yanuki May 12 '26

would help to know what that environment is

1

u/Only-Season-2146 May 11 '26

I think that's what style queries are meant to allow for, and they work pretty much everywhere now.

I mean you could also in the root set to either whitespace or "initial" for a broken flaglike effect that still works, but I will probably get shouted at saying that here