Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
Container queries via custom properties (aka CSS variables) #5
Comments
tomhodgins
commented
Dec 14, 2016
|
The problem I'm seeing with the first example is that they're based on viewport-percentage units, but the elements you'll need to be styling may not scale perfectly with the browser's width and/or height. What we need to do these kinds of calculations is a unit that is aware of the width and height of the element as it appears on the page (not as we want it to appear). With that information we could write the kind of code in the first examples. Consider the difference in syntax between the two following examples - the first uses JavaScript to check the <div class=demo-1></div>
<style>
@element '.demo-1' {
$this {
background: lime;
height: eval('offsetWidth / (16/9)')
}
}
</style>
<script src=http://elementqueries.com/EQCSS.js></script><div class=demo-2></div>
<style>
@element '.demo-2' {
$this {
background: orange;
height: calc(100ew / (16/9));
}
}
</style>
<script src=http://elementqueries.com/EQCSS.js></script>I think before a solution like this would be usable, we would need As for the conditional Here's a version of your <img src=http://staticresource.com/user.png class=component>
<style>
@element 'html' {
img {
float: eval('innerWidth > 200 ? "left" : "right"')
}
}
</style>
<script src=http://elementqueries.com/EQCSS.js></script>And then here are other ways I've used Min/Max font-size@element '[data-min-font],[data-max-font]' {
$this {
font-size: eval('
var vw = innerWidth/100*10, /* equal to 10vw */
min = getAttribute("data-min-font"),
max = getAttribute("data-max-font");
if (min !== null && max !== null) {
vw <= min ? min : max <= vw ? max : vw
} else if (min !== null) {
vw <= min ? min : vw;
} else if (max !== null) {
max <= vw ? max : vw;
}
')px;
}
}Sniffing Element Orientation@element 'div' {
$this {
background: eval("
offsetWidth == offsetHeight ? 'blue'
: offsetWidth > offsetHeight ? 'green'
: offsetWidth < offsetHeight ? 'red'
: null
")
}
}
Faking :in-viewport@element 'p' {
$this {
/* Color is red when partly in-viewport */
color: eval("
var top = offsetTop - innerHeight;
var bottom = top + offsetHeight;
if (
(scrollY < offsetTop + offsetHeight)
&& (top < scrollY)
&& (bottom < scrollY + offsetHeight)
){
'tomato'
} else {
'inherit'
}
");
/* Background is green when fully in-viewport */
background: eval("
var top = offsetTop - innerHeight;
var bottom = top + offsetHeight;
if (
(scrollY < offsetTop)
&& (top < scrollY)
&& (bottom < scrollY)
){
'darkgreen'
} else {
'inherit'
}
");
}
}Centered or OverflowThis example below uses @element 'div h2' {
eval('offsetHeight <= parentNode.offsetHeight ? "$this" : ""') {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
eval('offsetHeight >= parentNode.offsetHeight ? "$parent" : ""') {
overflow: auto;
overflow-y: scroll;
border-color: lime;
}
}Using If statement as selectorIn this example we use JavaScript to check the <div style=background-image:url(http://staticresource.com/user.png)></div>
<div style=background-image:url(http://staticresource.com/nebula.jpg)></div>
<style>
div {
height: 200px;
}
@element 'div' {
eval("window.getComputedStyle($it).backgroundImage.indexOf('nebula') !== -1 ? '$this' : '' ") {
border: 10px solid lime;
}
}
</style>
<script src=http://elementqueries.com/EQCSS.js></script>Based on these experiments and more I think that having container-style queries so we can write conditions once and affect styles for many elements is better than writing conditions many times in many rules. Another takeaway is that having an Should the |
ausi
commented
Dec 18, 2016
•
I used the viewport units as an example, the CSS author could set the CSS variable to whatever suits best. An element with a fixed width like
IMO that’s exactly the thing that is hard/impossible for browsers to implement, because it has to jump between layout and style computation. For setting aspect-ratios we may get a new property in the future, this is not a topic for container queries IMO.
Your
Using .component {
if(var(--context-width) > 200px) {
float: left;
background: red;
}
else {
float: none;
background: green;
}
}or: .component:if(var(--context-width) > 200px) {
float: left;
background: red;
}
.component:if(var(--context-width) <= 200px) {
float: none;
background: green;
} |
ausi
commented
Mar 6, 2017
|
I proposed the CSS conditions feature on WICG Discourse: And wrote an article on how they might be an alternative for container queries: |
tomhodgins
commented
Mar 6, 2017
|
Hey @ausi, great idea putting it on WICG Discourse to gather comment, it'll be great to see what people have to say! In your article you refer to the circularity problem with element/container queries, and today I recorded a video about this very issue: https://www.youtube.com/watch?v=QfM_JwSDdjo
I think there's a way to handle circularity that makes sense to how CSS works already! |
ausi
commented
Mar 6, 2017
I don’t think that’s true for container queries. I watched your video, but I don’t think |
beep
commented
Mar 7, 2017
|
@ausi: I just gave https://au.si/css-conditions-cq-alternative a quick read, and found it really interesting. I’m ~offline this week, but give a quick |
ausi
commented
Mar 7, 2017
|
@beep: Awesome thanks! I’m looking forward to it :) |
FremyCompany
commented
Apr 20, 2017
|
I had some thoughts about this today, and was thinking about how this could allow to choose among a set of differing layouts easily without need to extend this further, and wrote this: https://jsfiddle.net/35758bg7/1/ (basically you can duplicate all your layout paths and then from there choose one based on settings a small subset of properties on it based on --width) Posted this here just not to loose it, I don't say this is very smart or relevant, just didn't know where to post it otherwise :) |
ausi commentedDec 13, 2016
•
Edited 1 time
-
ausi
Dec 13, 2016
I’ve got a new idea for a solution to container queries🤓
What we already have today
To describe the concept, lets first take a look at what we already have in browsers, imagine the following setup:
Now I can create a component that is in a 16:9 ratio to its context width as easy as:
No matter how nested the
one-thirdandtwo-thirdscontainers are, acomponentinside them or at the root level would always be in the desired 16:9 ratio. This works already, although we need to hack a little because it’s not allowed to reference a CSS variable itself while setting it, take a look at this CodePen.New concept for CSS conditions
If we take this idea further and introduce a concept for custom property conditions with this syntax:
we could do something like:
This way we told the🎉
componentto only float left if it’s in a context (or container?) with more than 200px width, otherwise it should not float. Sounds pretty much like container queries to meFrom the perspective of a browser
My knowledge for browser internals in very limited, but AFAIK one big problem with an implementation of container queries is, that the engine would have to jump between layout and style computation, which could result in unstable results and might be very bad for performance. I think the concept of simple CSS conditions would not suffer from that problem. Taking the example from above, the condition
var(--context-width) > 200pxcan be worked out without the need for a layout. First thevar()part would be resolved to something likecalc((100vw / 3) / 3 * 2)and further to22.22vw. This value can then be easily compared to200px.Flexibility
Another benefit I see with this solution is, that the CSS author can decide how to set and inherit the variables. If one creates a website which has bright and dark sections, he could set
--context-darktotrueorfalseand create components that just look perfect in every place. Such binary conditions already work in browsers today if you are very creative.Downsides
The main downside of this solution is that we need to set variables for every container that changes the available width for its children. And we would sometimes not get the “exact” value if e.g. a scrollbar reduces the available width.
What do you think?