-
Notifications
You must be signed in to change notification settings - Fork 669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[css-env] Adding custom env() variables #2627
Comments
I think the general idea is to allow script to set them. But it's probably a good idea to allow stylesheets specify default values to them. Probably something like @env {
--some-width: 30em;
--some-color: #000;
} works. |
What would the advantage of 'custom These |
env() is guaranteed global, which means you can store them in a much more memory-efficient whole-page data structure, rather than on each individual element like currently. (Chrome, at least, attempts to detect custom props that are set on the root element and not set anywhere else, and automatically upgrade them to such a data structure.) env() also should be usable in further contexts outside of properties on elements, such as in MQs. This is fundamentally impossible with var(). |
I hope this is the place for ideas to prevent use of author-defined In #3285 (comment) @tabatkins says...
Any thoughts on what @upsuper points out in #2627 (comment)? |
I hope the implementation of how users can define environment variables can happen at the same time or shortly after the implementation of referencing env variables. |
@tomhodgins re
media queries can't use Use case: in In my case, I have a calculated "base font size" that grows/shrinks based on window width, but stops at min/max values at specified min/max width. Yeah, accessibility issues if I do this wrong, so I may end up with javascript to resolve the various inputs to this calculation, but that isn't the point here. Unless |
Sounds like a job for :root {
font-size: clamp(10px, 10vw, 50px);
} As for using custom identifiers in Media Query conditions, though you do need to process it (either ahead of time, or at runtime) there's already flexibility in CSS to allow you to encode some nice breakpoints, and write at-rules that use those user-defined breakpoints, and interpret those at-rules as though they were media queries written for the values those custom breakpoints represent: :root {
--breakpoints: {
"narrow": "(min-width: 300px)",
"medium": "(min-width: 600px)",
"wide": "(min-width: 900px)"
}
}
@supports (--breakpoint("narrow")) {
html {
background: red;
}
}
@supports (--breakpoint("medium")) {
html {
background: green;
}
}
@supports (--breakpoint("wide")) {
html {
background: blue;
}
} Demo: https://codepen.io/tomhodgins/pen/yLBOyBe So nothing else needs to be added to CSS to accomplish either the scalable font-size functionality where a scalable unit is capped with a minimum and maximum it won't go beyond, as well as the ability to encode custom breakpoint names and refer to them, though for the second one you'll need a little bit of code to help either in advance, or like my Codepen demo in the browser at runtime :D |
@tomhodgins I'm not sure why you seem to be arguing against user-defined environment variables? 🤔 There's no potential conflict if user-defined environment variables need to be prefixed with |
Please don't think I'm arguing, nothing I'm saying here is meant like that at all! 😩 I'm showing some things the platform can do, no hostility intended. |
@tomhodgins Ah okay, fair enough. Sorry if I misunderstood your position! |
Hello, @tomhodgins: But... So For variables media queries breakpoints, we can imagine two simple possibilities. I think the first solution may be reasonable (and then may needs another ticket if not already existing). But it's only my point of view. |
Maybe something like this: @constants {
--my-unalterable-var: my_Value_That_Is_Selector_Context_Agnostic;
--breakpoint-s: 640px;
--body-bg: blue;
}
@media screen and (min-width: var(--breakpoint-s, 300px)) { /* because constants are selector agnostic */
body {
--body-bg: red; /* no effect, because --body-bg is already a constant (then it's unalterable) */
background-color: var(--body-bg, green); /* blue, because --body-bg is simply already defined */
}
} (if --breakpoint-s is not set as constant, then media query min-width value will be 300px) I'm going to |
Hi, It's a bit related: I would like to override official My case is simple: I found a bug about its usage inside a hybrid native application and I would like from my desktop to simulate If not, I think it would be helpful to simulate some cases where nested blocks use it and make things going wrong 😄 Thank you, |
@sneko IMO maybe the best way to handle that is to have a syntax that allows you to pull in an env() constant and set it to a new, global variable that you can reference? I think overriding a value provided by the environment feels out of scope. |
@sneko have you found a way since August ? |
@Aarbel I didn't. As @matthew-dean mentioned, I think the best is to think about it as a variable when you begin a project (assigning the real |
@sneko thanks a lot for your quite feedback ;) Can you just give a little example ? |
I didn't make the modification yet (as a quick workaround I just replaced all values since it was scoped to only 1 repository) but I would think about defining something like:
And when you want to use it:
|
This solution seems like the most obvious choice to me, especially considering how it very closely mimics an already-existing feature, |
Being able to also set this css thru javascript would be the best |
I am also interested in having custom environment variables, exactly for use in media queries (for breakpoints and similar), where we can't use regular variables. Are there any plans to introduce this? Solution proposed earlier seems good, and shouldn't be too hard to implement.
|
There’s some overlapping discussion that went on in #6641, suggesting |
I would like to know if it would be possible to import constants in CSS. Would it be possible to import constants in CSS? (you all are talking about an alternative to custom media and custom selectors, would it be possible with constants or env... be something imported? For example:) filename: constants.css @constants {
--my-unalterable-var: my_Value_That_Is_Selector_Context_Agnostic;
--breakpoint-s: 640px;
--body-bg: blue;
} filename: main.css @import "constants.css" constants, breakpoint-s, body-bg;
@media screen and (min-width: var(--breakpoint-s, 300px)) { /* because constants are selector agnostic */
body {
--body-bg: red; /* no effect, because --body-bg is already a constant (then it's unalterable) */
background-color: var(--body-bg, green); /* blue, because --body-bg is simply already defined */
}
} (I find this proposal very interesting, technologies like javascript, typescript have a feature similar to this. But I don't know if you all know, but I think it would be really cool to import constants in a CSS code snippet) filename: constants.js export const bodyBg = 'blue'; // 'green'
export const breakpoints = '640px'; // 'green' filename: main.js import { bodyBg, breakpoints } from "/constants.js";
console.log(bodyBg); // blue
console.log(breakpoints); // 640px Note: (Something I noticed when importing variables of type const in javascript is that variables of type const in javascript cannot change their value or be overwritten. I believe this is due to the fact that they are block-scoped. I think this should change in css, as variables in css can change their value and it wouldn't be const type.) But my doubt would be if it would be possible to import css variables also inside the import - I don't know if the variables in css are of type const in "block-scoped" in js or are global like "var" as js too. |
My concern with this proposal is that the syntax of constants clashes with that of custom properties. I think they should be obviously distinguishable from each other, as examples like these could be really confusing. @media screen and (min-width: var(--breakpoint-s, 300px)) { /* because constants are selector agnostic */
body {
--body-bg: red; /* no effect, because --body-bg is already a constant (then it's unalterable) */
background-color: var(--body-bg, green); /* blue, because --body-bg is simply already defined */
}
} Here, an author would have to go through the entire stylesheet and imports to see why |
Looking at your feedback and comment, from what I said earlier it would make sense then to assume that this custom env() is then a "var" (since it can change the value) and not a "const" (because cannot change the value) My concern is similar to yours(this proposal is that the syntax of constants clashes with that of custom properties). Another concern I have is how to import this, and whether or not there will be import like js does. One of my concerns is that import doesn't allow special symbols in variables. Example: filename: main.css @import "constants.css" constants, breakpoint-s, body-bg;
/* error breakpoint-s, body-bg
symbol not allowed for import -
*/
@media screen and (min-width: var(--breakpoint-s, 300px)) { /* because constants are selector agnostic */
body {
--body-bg: red; /* no effect, because --body-bg is already a constant (then it's unalterable) */
background-color: var(--body-bg, green); /* blue, because --body-bg is simply already defined */
}
} vs filename: /constants.js export const body-bg = 'blue'; // 'green'
export const breakpoint-s = '640px'; // 'green' filename: /main.js import { body-bg, breakpoint-s } from "/constants.js";
/* error breakpoint-s, body-bg
symbol not allowed for import -
*/
console.log(body-bg); // blue // error import
console.log(breakpoint-s); // 640px // error import For me it wouldn't make sense to create custom variables if I can't reuse them in imports. As I said above, if this is used as an import, would it make sense to allow names with special characters? |
This sounds to me that you want to have this :
Which sounds more like what design tokens are trying to solve? |
Worth pointing out that the distinction between This is also why |
@ghost I think you make a good point that environment variables may be a special case where the referencing in CSS should be allowed in camelCase or dash-case (to point to the same var / value), and similar to the API for style properties, would be presented to JavaScript in camelCase even if they were defined as dash-case. This would allow the same interoperability that style values have now. It's possible environment variables already have this in the spec, I don't know. |
I think part of the issue @ghost is pointing out is that an env variable would theoretically be global for the environment (the window), which could lead you to the same types of problems when we used to do global vars in JavaScript, which is global pollution but also naming clashes. Probably an explicit import would be preferable, which maybe points to a 3rd type of variable, or a way to define importable local variables, similar to what @jonathantneal originally posted, but combined with the syntax that @ghost mentioned. As in: // vars.css
@var --breakpoint-s 320px; // main.css
@import "vars.css" --breakpoint-s;
@media screen and (min-width: var(--breakpoint-s, 300px)) {
body {
background: red;
}
} It maybe has some confusion about where the value would be available, or which var could be used where, but other languages also have scoping rules for variable access. Otherwise there might have to be a third "variable" construct. |
I'm not 100% convinced that global variables are a problem here; JavaScript's global variables are a problem because they can clash with built-ins and other namespaces, whereas global environments in CSS would just be local to the styles, and nothing else. CSS has its own rules for handling conflicts, and I don't see a meaningful distinction between global environments and variables defined on Like, I could see an argument in favour of allowing |
🤔 I guess, to be fair, custom properties defined in |
Mostly just to solidify the argument, we already have two things decided by the standard:
You could argue that there are shortcomings of this approach, but that would require a completely separate proposal, rather than just one that lets you define environments, since the distinction between variables and environments already exists. Really, the only question is syntax, since CSS has a few standard things that we can work off of:
Additionally, although it's not strictly required, it makes the most logical sense to simply borrow the syntax for defining variables as properties and instead define a block syntax that makes these properties turn into environments instead of variables. So, it would make sense to have something like There could be a separate proposal to allow modules or namespaces which could later be expanded to include environments, but this wouldn't be part of environments themselves. It's a separate problem that people have tried to solve, but IMHO it's orthogonal to the concern of defining custom environments. Keyframes are a good example of this since these are also globally named. |
This is a very interesting discussion! I believe being able to set our own environment variables that can be used inside MQ is very exciting. I find this to be especially powerful if we can override those values depending on the window. Perhaps one could use javascript to, for example, measure the width that the browser is giving all scrollbars and pass that to CSS as an environmental variable
There are definitely other ways to do this that don't require MQs or environmental variables at all, easily being implemented with normal custom properties and I guess this dynamically changing environment variables should only be possible with js, since doing so from CSS could bring some infinite loop problems like for example:
This is definitely something to think about. Maybe this is all out of the scope of css and actually better off being done another way from js, instead of trying to make MQs act like js if statements. On another note, how would the syntax work for using these environment variables in media queries? Will I only be able to query for the exact value? Or would there be any ranges possible? Something like:
I guess this would bring its own set of complexities. I imagine this wouldn't be possible unless we can define the |
@nasif-co, your use case is already partially resolved with style queries and will be fully resolved if the working group accepts #8376. Sample code: |
https://drafts.csswg.org/css-env-1/
What are the current ideas being pitched to add custom env() variables via CSS?
To add custom env() variables, could a similar syntax be used as seen in custom media and custom selectors?
Or what other issues might there be?
While I feel like the answer should be “not yet”, if the answer to this question is yes, could syntax like
@media
(curly braces) be used?As for JS, I hope that can be resolved separately via Houdini, because I’m under the impression there are still many things to work out with the similar concept of custom properties (as well as shorthands which apply to both, or selectors and rulesets that could apply to
env()
) .The text was updated successfully, but these errors were encountered: