Closed jehoshua02 closed 9 years ago
Can you give an example of where this would help that couldn't be addressed by just putting the styles into the element directly?
Hello @tabatkins! I'm excited by the effort I'm seeing here.
In order to answer your question I'd need to see a more concrete example of the proposed element query syntax.
What about something like this?
.element {
/* default .element styles */
}
.element (min-width: 300px) {
/* styles when .element width is greater than 300px */
}
.element (min-width: 480px) and (max-width: 768px) {
/* styles when .element width between 480px and 768px */
}
If the syntax were something like this, I would expect it to be based on the .element
width, not it's parent.
Maybe that looks too much like a normal css rule?
@element .element (min-width: 300px) {
.element {
/* styles for .element when .element widht is greater than 300px */
}
.element .child {
/* styles for .element .child when .element width is greater than 300px */
}
.element .another-child {
/* styles for .element .another-child when .element width is greater than 300px */
}
}
I would expect this element query to be evaluated for each element matching selector .element
and the styles only being applied to that individual element if that individual element's width matches the criteria.
Did I just open a can of worms?
Syntax doesn't actually matter; I was just looking for an example of what you'd actually want to do with it.
Seems like element width is either pre-known (if it's a definite length) or directly calculated from the container's width (if it's a percentage); the former means you can just write your CSS against that length, the latter means you can use an EQ against the container width. EQ against the container allows for more things, as well.
Do you have an example of something you want to do with EQs that would be easier if it was based on the element instead (or even better, difficult/impossible to base off the container)?
To be honest, I haven't been working with element-level breakpoints long enough to have some really solid examples.
The reason I brought it up is that It feels illogical to rely on the parent width when what you really care about is the element width. And when looking at the code, I'd want to read it something like this "When the element has a width of X, style it and it's children like this ..."
Typically, I just want to style the children of the element, to shuffle the layout of the child elements so they fit better based on the element's width. Perhaps I need to read it closer.
I understand that developing standards probably requires more than just "feelings". So let me think about it and see if I come up with some examples. Heck, you might come up with an example before I do.
As far as syntax, the parent should not be part of the syntax, since I want the element to look right no matter what it's parent might be.
On the other hand, perhaps you could point me toward an explanation why the parent width is preferable? My stance is still susceptible to change. Maybe what you call "parent container" is what I'm calling "element"? So maybe there is no difference in what we are talking about only how we say it?
I wrote a library breakpoints.js. That's probably the best reflection of how I think about element queries. You'll see that I use the element's own width when evaluating the breakpoint. Actually, I use the element's "outer" width (probably another discussion what "width", in the context of EQs, actually means: content-box, padding, border, margin, box-sizing, etc).
What I could do for experience is branch breakpoints.js and see what it would look like if I base it off parent width and get back to you.
If you just need to style the children, that means the element itself is the container (for the children). They can respond to the element's width using the existing mechanism.
It seems that the current use case proposal is based on modular elements wrapped in columns used for layout (think Bootstrap). By basing the element query on the width of the parent, this use case works beautifully, as layout and components are on separate levels within the DOM.
One use case that comes to mind where it might be necessary to rely on the width of the element itself is when flexbox is used to define the width of components. In these cases, width of the element is unknown until the flexed layout is calculated, and the width of the parent is irrelevant. I suppose the EQ could be applied to only elements inside one of these flex-sized elements, but then you'd be enforcing a specific DOM structure on the use of all elements using EQ's.
@alanmoo I might be missing the point of your comment. I also might be bikeshedding. Let me know.
If I understand correctly, we have a series of blocks in a container. To style the blocks, particularly the layout of content within the block, you can attach the EQ in two places: on the container or on the blocks within the container.
My two cents:
All of your use-cases are about styling the contents of a block based on the size of the block. That's an EQ-on-container, where "container" is the block and "stuff responding to EQ" is the contents of the block.
Maybe you're interpreting "container" too literal-mindedly?
Bottom line: Something rubbed me the wrong way about the wording in that paragraph. My proposed change isn't quite right either. So I need to help come up with something else. How about this?
What this document proposes is the addition of an “element query” syntax,
allowing breakpoints to be applied based on the width of a parent containerallowing styling of an element's children and/or itself based on the element's width. For the purposes of this example, we would be then be able to scope out modules’ layouts to the size of the module itself.
Also, there's probably fewer use cases for it, but what about other properties besides width? There's nothing in the EQ name that says it's limited to just the width property.
What this document proposes is the addition of an “element query” syntax,
allowing breakpoints to be applied based on the width of a parent containerallowing styling of an element's children and/or itself based on the value of one or more of the element's properties. For the purposes of this example, we would be then be able to scope out modules’ layouts to the size of the module itself.
@tabatkins Yes. Everything is a block. And most use cases are setting EQ on block and styling contents.
I think I was just looking for consistent language. After all, it is an "element query". Not a "parent query".
To me it wasn't clear enough what a "breakpoint" is, what it's "applied" to, what we are styling (the EQ target element's children and/or itself), and what the target of the EQ is (width on an element).
I'm probably just swallowing the elephant and straining at the gnat here.
allowing styling of an element's children and/or itself based on the element's width
Again, styling children is fine, with the EQ magic that makes the parent pretend it doesn't have any children when sizing itself. But styling the element itself is really circular. However, none of the use-cases you've described seem to require that.
After all, it is an "element query". Not a "parent query".
It queries the size of an element, as opposed to a "media" query that queries the medium the page is rendered on.
The terminology around "breakpoints" is fairly common in responsive designs; we can clear it up, of course.
Hello all. I'm doing my Master's Thesis regarding element queries. I've been lurking around for a while reading your discussions. Now I've got to the point where I feel like I need to start asking questions. I hope I won't be too troublesome for you guys :)
@tabatkins When I first thought about how EQ would work, I too as @jehoshua02 based my approach on having the queries targeting any element (as opposed to the only container elements). I understand that it might usually (or always) be the case that you want to query the container, but I'm trying to understand why this limitation is a good thing. You wrote earlier:
EQ against the container allows for more things, as well.
Could you please elaborate on that?
Thanks
@wnr I think in the end, @tabatkins and I realized that we were talking about the same thing. What I was trying to point out, not very articulately or precisely, is the inconsistency in language. They are "element queries" -- queries against an element. Not "container queries". But they are essentially the same thing, it's just what element, or context, from which you are looking at it. I apologize if I have caused any confusion.
@jehoshua02 Thank you for your quick response. From what I understand of your discussion here I don't think you are talking about the same thing.
Forgive me for bringing syntax into the discussion (but I feel like it's needed to not get confused about terminology). If we forget about valid use cases for a while, there is clearly a difference between the following two approaches:
Let's say we have this piece of HTML in a module (we don't know the surroundings):
<div id="container">
<div class="child"></div>
<div class="child"></div>
</div>
The approach Tab seems to be recommending
This would restrict us to only be able to apply rules on the child
elements, right? Like so:
.child {
background: red;
}
/* Made up syntax. Will only match if the #container element is between 600 and 1000 pixels wide. */
#container:eq(min-width:600px and max-width:1000px) .child {
background: blue;
}
So this example will make the children of the container colored blue when the container element is of a width between 600 and 1000 pixels. Otherwise the children will be red.
The approach jehoshua02 (and I) seems to be recommending
.child {
background: red;
}
/* Made up syntax. Will only match if the #container element is between 600 and 1000 pixels wide. */
#container:eq(min-width:600px and max-width:1000px) .child {
background: blue;
}
/* Made up syntax. Will only match if the #container element is above 1000 pixels wide. */
#container:eq(min-width:1001px) {
background: yellow;
}
So with this approach it is possible to also color the container element based on it's own width. The children will behave exactly as in approach 1. The difference is that the container will be colored yellow when the width of the container is above 1000 pixels.
I do realize that the outcome of approach 2 is possible to achieve with approach 1 by wrapping the content by another container like so:
<div id="outer-container">
<div id="container">
<div class="child"></div>
<div class="child"></div>
</div>
</div>
.child {
background: red;
}
/* Made up syntax. Will only match if the #outer-container element is between 600 and 1000 pixels wide. */
#outer-container:eq(min-width:600px and max-width:1000px) .child {
background: blue;
}
/* Made up syntax. Will only match if the #outer-container element is above 1000 pixels wide. */
#outer-container:eq(min-width:1001px) #container {
background: yellow;
}
So it seems to me that everything you can do with approach 2 you can also do with approach 1 by adding extra markup. The question is if it holds the other way around. Can you by using approach 2 do anything you can do with approach 1? I can't come up with anything that you cannot do. If I didn't misunderstand @tabatkins when he wrote EQ against the container allows for more things, as well.
means that Tab have thought of something that cannot be done with approach 2, but can be done with approach 1. That's why I would like Tab to elaborate on this :)
If you two indeed have been talking about approach 2 all along, I believe the document should be changed according to your initial issue proposal.
Sorry for the super-long post.
@wnr I vote for approach #2. That's what I imagine when I think EQ. Is syntax abstinence stultifying our discussions?
Aren't both approaches the same thing? From what I can gather you would be able to set an EQ on any element and you wouldn't need to specify a child unless you wanted to. That would be a weird constraint given how CSS selectors all currently work.
What might be meant with the container is that the containers width would be used in determining of an EQ matches when the element it is specified on has width: auto
?
An important discussion might be what to do if an element width is set to an absolute value like width: 500px
, would it only ever match an EQ for 500px (or a range that holds 500x) or would it listen to the space the parent gives it? The latter which is problematic if you're using percentage widths.
And what if an element matches an EQ that sets an absolute width meaning the element is "locked" to that EQ. Or even better (and discussed elsewhere in this repo) if an EQ sets a width that triggers another EQ which could easily result in infinite loops or at least a buggy mess? The solution there would be to ignore any CSS value that triggers layout of course, but would we want that? You would at least want to be able to set position: relative
so you can absolutely position other elements in the element.
Re-reading this thread I think everyone is talking about the same thing and has the same goal. The confusion is around how widths for the EQ element are determined.
I think we shouldn't allow the element on which the EQ is on the set it's own width, but that is will of course listen to it's own width (which is the entire point of EQs).
A containing element would however be able to set children widths. That way you can make a container with children morph from a stacked row layout to a column layout based on the width of the container. The children within the container would have their own styling based on their EQs.
And if a container is a certain width, the children within it would be able to have an absolute width as long as they can't set it on themselves with their own EQs (in which case it would never change anymore).
So in code terms (just to make it more clear):
/* This shouldn't be allowed */
#container .child(min-width: 300px){
width: 200px;
}
/* This should be allowed */
#container(min-width: 300px) .child{
width: 200px;
}
@PaulSpr
Aren't both approaches the same thing? From what I can gather you would be able to set an EQ on any element and you wouldn't need to specify a child unless you wanted to. That would be a weird constraint given how CSS selectors all currently work.
I realize now that I wasn't too clear in my example of approach 1. I indeed meant that in approach 1 you can only query parents, meaning that you are required to specify a child in the selector. This is my interpretation of what @tabatkins is recommending (and probably rightfully so due to implementation specifics). So with that clarification, the two approaches are clearly not the same. Approach 1 is a subset of approach 2. In other words approach 1 is the same as approach 2 only with the constraints that you have to specify a child in the selector (i.e. writing the EQ against the container/parent of the element that you want to style).
I am aware of the implementation problems that approach 2 brings, and I do understand that approach 1 is more valid in terms of performance of rendering engines (from what I gather from the mail conversations at org.w3.www-style). However, I think this is not the place for taking that into consideration, since we only want to talk about use cases here and keep all implementation/solution specific things out. Although I think you have many valid points @PaulSpr I believe it is too early (or not the right place) to discuss or even think about those things. The only reason I brought this up is to change the document paragraph:
What this document proposes is the addition of an “element query” syntax, allowing breakpoints to be applied based on the width of a parent container. For the purposes of this example, we would be then be able to scope out modules’ layouts to the size of the module itself.
Because it can now be interpreted as that the document is assuming approach 1. Since this document should only address use cases, I think it should be changed.
My suggestion is to the following:
What this document proposes is the addition of an “element query” syntax, allowing
breakpoints to be applied based on the width of a parent containerconditional style rules to be applied to elements based on element dimensions. For the purposes of this example, we would be then be able to scope out modules’ layouts to the size of the module itself.
Or something similar (leaving the words parent, container and self out of the description). Keeping it a bit vague about syntax/approach specifics.
@wnr I always assumed that approach 2 was the way EQs would work. So I also agree with the more vague description.
That said, even though we are now in the use-case phase of the proposal, how they would actually work is important. Especially given the main use-case: Creating adaptive layout pieces.
A good example is the representation of a book, let's call it a cover layout, with a title, cover, author, publish date, publisher, genre, etc.. When viewing a review of the book, the cover layout is in a small sidebar. Under the review there are two related books using the cover layout in 2 columns. One another page there is an overview of all the books with a 4 column layout. This is all for a desktop kind of layout.
If we write EQs against the cover layout width (approach 2) we get super simple and very efficient CSS.
If we write EQs against the elements containing the cover layout elements (approach 1) we would probably have a lot of the same code in each of the containers. The related books for example would at some point (small screen) get the exact same layout as the book in the sidebar. These styles would then be present in both the sidebar containing element as well as the related books containing element.
If an element could be a standalone piece of layout/content it should be responsible for its own layout, but let its size be dictated by what its parent says it should be.
This goes many ways. In the book example the cover layout is responsible for its layout in different sizes, but the related books layout (which contains 2 cover layouts) is responsible for its layout, in this case how the cover layouts are arranged. Think: 1-column, 2-columns, the spacing between the elements overall background color, etc.. This changes the size of the elements it contains, which themselves present them in the best possible way.
@PaulSpr I agree. So how do we move forward from this? Any input from an owner of this repo? I'll create a PR in the meantime.
The fundamental technical issues against an element's styles depending on themselves still apply. We can't reasonably apply selectors against an element's own width for styling itself; it has to be a container with certain properties (namely, that it no longer pays attention to its children when computing certain dimensions of its size).
I recognize that this makes some cases harder to write, and there might be some cases that it makes impossible, but it's unavoidable technically.
@tabatkins
So you are saying that this ...
#container:eq(min-width:1001px) {
background: yellow;
}
... is technically impossible?
Bummer.
Rather, that allowing that implicitly allows cases that are technically impossible.
Okay so we at least have a definite answer now, and are not stuck in the "we are talking about the same thing". For those of you that are unfamiliar with the constraints that Tab is talking about here is a mail conversation that I think explains it pretty good: http://markmail.org/search/?q=%22The+%3Amin-width%2F%3Amax-width+pseudo-classes%22#query:%22The%20%3Amin-width%2F%3Amax-width%20pseudo-classes%22+page:1+mid:i5abwvvbm6dakwxb+state:results
I thought this document was supposed to be solution-less and not conforming to implementation issues, but I guess it could be wise to have it doing so.
Shouldn't the document state the assumptions we make about constraints and the API?
I propose element queries should be based not on the parent width, but on the element width. The element might be constrained in some cases to a fixed width while the parent may be larger.
I would modify the document as follows:
I haven't read any farther than this yet. There may be other modifications necessary to keep everything in harmony.