Media Queries are a Hack
ianstormtaylor.com
ianstormtaylor.com
The BEM architecture calls these "Modifiers" (http://csswizardry.com/2013/01/mindbemding-getting-your-head...).
When I look at your example, I don't think of a .testimonial object in two different contexts (one vertical in the sidebar of the signup page while one horizontal on the pricing page). Instead, I think of two different variations of the .testimonial object. So while your .testimonial class may define certain global styles, you change what you need by variations like .testimonial.vertical or .testimonial.horizontal (though I wouldn't actually use those names, but you get the idea).
This requires making a decision on when to apply what classes, but that's okay. You shouldn't be trying to abstract away actual UI decision-making to an automated tool or process. You seem to think that settings rules and logic to be executed based on those rules (when x, execute y; when y, execute z; etc.) will mean you always end up with a usable interface. However, this is not the case.
Ultimately, UI is not "write-once, use anywhere", and that's okay.
Element queries as described by the author address an entirely different set of concerns, which is that modular components of HTML might be re-used in varying situations, and depending on the implementation you might want to style them differently. Media queries are the wrong tool to solve this problem.
The problem is that when we want to use this:
.testimonial (max-width:27em) {font-size: 0.8em;}
We have to use a context-specific style definition instead: .testimonial {font-size: 1em;}
.signup .testimonial {font-size: 0.8em;}
Or, better (from the parent): .testimonial.vertical {font-size: 0.8em;}
.testimonial.horizontal {font-size: 1em;}
You might still have to revisit each of these styles in a media query to apply changes depending on the global presentation. So while the proposed element query might eliminate the need to chain selectors, I do not believe that it simplifies media queries in any meaningful way. .testimonial.vertical
.testimonial.horizontal
By including those classes in the actual markup you're hard-coding semantics about the presentation of those two elements that may cease to be relevant when the screen changes width. What if when the screen gets sufficiently narrow you want the horizontal layout to actually change to vertical? The breakpoint at which that happens is more closely linked to the size of the element than the global size of the whole screen (which media queries relate to).So the point is that with element queries you're defining modular breakpoints that directly relate to your CSS modules, not the global size of the screen, and you're not polluting/complicating markup with CSS class names that could become non-semantic in drastically differing viewport dimensions.
I think the core of the problem is that CSS was designed to style documents (because the web long ago was more or less a collection of text documents), but as the web evolved, it became necessary to use CSS for styling UIs--an entirely different beast from documents.
This twisting has led to the state we're in now, where CSS creates the problem it tried to solve: updating a style on a medium-complexity web site requires digging through a minefield of complex and interconnected CSS. Yes things like SASS or LESS can help but they're not an ultimate solution, nor are they a web standard, so tying your horse to one of those carts can limit you in the future.
Maybe in CSS5 they can add proper object-oriented syntax and element queries to help increase modularity and reuse and decrease cascading and media query complexity.
Its an add-on to a markup language also built mostly only to display text.
A more constructive angle to this debate would be to compare HTML/CSS to other declarative UI frameworks such as those in QT and iOS and discuss what features need to be added or removed to make HTML/CSS more maintainable and less painful.
We all know the history of HTML and we're aware of the path it's evolution has taken.
Are you arguing that it's inherently unfixable and needs to be scrapped? I think you'd have a tough time arguing that point so why not move the debate forward instead of playing the curmudgeon?
CSS has the cascade and @import and background-image links for example, but historically the document was typically one text file and some pictures; an app's UI is combined from many source files and subordinate resources. CSS works pretty well for declaratively styling a monolithic document, but it is not entirely satisfactory for styling the UI of complex app such as Facebook.
I ask not to be snarky, but ... I've never really been satisfied with CSS. CSS proponents have shouted me down (figuratively) for being a 'tables' holdout, but it felt to me like we traded super-nested tables with ALIGN and CELLPADDING attributes for box-model hacks and numerous interpretations of the word "may" and "should" from years-old spec docs; it didn't feel like that much of an improvement in many cases.
Do browser makers consult 'regular' web developers before coding in new browser-specific CSS extensions?
HTML and HTML2 were developed by developers (via the IETF).
HTML3->HTML4->XHTML and CSS1->CSS2 represent increasing control by academics in committees at W3C.
HTML5 and CSS3 are the result of fed-up actual web developers stepping up.
What gets implemented in browser-specific extensions is some combination of governing committees and developers actually willing to write the code.
There's a long list here: http://www.w3.org/Style/CSS/members. A quick look at LinkedIn profiles seems to indicate a lot of them are end users.
Unfortunately, even for static CSS, that's not going to be practical for element queries. You could do it in theory, but in practice, you'd end up generating tons and tons of CSS for even very simple sites.
>A shim is generally meant to be there just in case some feature (present in some modern browsers) isn't available in the current browser;
That's why I put "shim-first" in quotes.
The first can only be done by CSS in the browser. But the second can be accomplished via CSS, or by JavaScript.
As the web evolves, CSS for layout is increasingly not keeping pace. But it's not unreasonable to think that we could do away with it altogether.
Is there anything preventing someone from creating totally new layout models, based on new formats, that are parsed in JavaScript, and essentially turn everything into div's with position:absolute? And get recalculated upon window resize etc.?
This would completely free us from existing layout limitations of CSS, to do the exact kind of things like element queries, or whatever else we might think of.
I'm just not really sure what the performance implications would be like.
In regard to your layout in JS question. There is an excellent port of the Cassowary constraint solver in JS [1]. It allows you to specify complex relationships between containers along with weights, which allow you to specify layouts in a sane manner. Performance is very good, especially since it takes advantage of web workers where available.
What I hate most about layout in CSS is that it takes something that should be brain-dead simple and turns it into something that requires memorization of edge cases and browser hacks with some added voodoo magic. It's such a waste of brain cycles.
To top it all off constraint based solvers have been around for over 20 years... and yet in 2013 we're still dealing with this mess.
Not having adequate Flexbox support after it being discussed for soooo long is my other big problem with CSS.
While we're at it lets scrap the DOM too. It's really painful to see how much it is being contorted to suit the application paradigm.
GridSet (http://gridsetapp.com) does some pretty amazing things. While it doesn't require you use a CSS preprocessor, you should check out the .scss it generates for a look into how they use preprocessor functions in a way that's much more similar to programming than CSS property-value lists.
You should also check out Chris Eppstein's deck on his approach to structuring projects with separated concerns (https://speakerdeck.com/chriseppstein/help-my-stylesheets-ar...), and Jonathan Snook's SMACSS (http://smacss.com).
I don't think this is necessarily true across the board. If you're creating just another brochure site then CSS does a good job of document layout and it's true that usign JS for layout is unnecessary and counter productive.
If, on the other hand, you're creating complex layouts that mimic desktop applications (complex components, nested panels etc), then JS for layout is the only sane option.
I think what you're referring to is using javascript to build flexible layouts that afford a significant matrix of collisions between elements (w/ variable dimensions) by programmatically evaluating, resizing, moving, etc. For example, desktop Chrome's tabs: shrinking them as they increase in number, adjusting their position to keep the close button under the mouse, etc.
But I'm having a hard time thinking of such beasts on the web, where such complications can't (or shouldn't) be limited by design. Share some examples?
http://layout.jquery-dev.net/demos/complex.html
http://developer.yahoo.com/yui/examples/layout/adv_layout_so...
https://gomockingbird.com/mockingbird/#
http://docs.sencha.com/ext-js/4-2/extjs-build/examples/build...
These layouts all use a combination of CSS for layout (floats, margin, padding etc) as well as absolutely positioned elements that are controlled using some variety of layout manager. Where this becomes especially useful is for collapsible, resizable, movable panels and windows.
A testament to the way in which CSS is lacking is evidenced through the hundreds of multi-thousand word blog posts that were devoted over the years to discussing how to achieve multi-column equal height flexible layouts [1]. This is something that should be trivial, instead hundreds of man years have been wasted trying to get boxes to line up nicely.
CSS3 flexbox solves some of these issues, however there is still no way in which to arbitrarily constrain or anchor any container to any other container which ultimately limits its usefulness.
How did I miss that until now?
Maybe we should update CSS to include object oriented features too. Then we can have abstract factory methods for our reusable components. Throw in an optional type checker for good measure while we are at it.
Please people, CSS and HTML only ever have had a single layout algorithm. Maybe it is not terribly flexible but it is good for limited width and unlimited unknown height presentation of a single stream of content. If your content genuinely calls for a different layout, please consider using something else other than CSS and HTML.
While I appreciate the endless efforts to workaround and improve the layout capabilities of CSS, may I suggest embracing the limited nature of this stack and design accordingly?
Maybe, if we admit the "content" arrive, is rendered and consumed sequentially, we would relieve ourselves the burden of beating CSS into submission whenever we want to diverge; with the added benefit of making life easier for those who can't see.
You wouldn't shy away from a little bit of challenge of learning something more suitable for you purposes, right?
As acabal notes, the core issue is that CSS was originally for styling documents, and media-queries work in that framework: they're about laying out or formatting a document, not a component within the document.
Which is of course the wrong approach if you're creating distributable/reusable components and blocks. Media queries are not a hack and are probably necessary: the final author will use them to lay out his site/page responsively.
But they're not sufficient, because the inner layout of a sub-element is impacted more by the element's size than the viewport's (the sub-element's positioning and size on the other hand are affected by the viewport).
All in all, the article is a good note of a real problem. But its headline stinks for the usual reasons.
.testimonial {
media screen and (max-width: 900px) {
font-size: 0.8em;
}
&.compact {
media screen and (max-width: 1200px) {
font-size: 0.8em;
}
}
}What if this thing shows up in 18 places, some of those change sizes on mobile, some of them in turn being reused in several places and then somebody changes something that affects the size (and therefore desired styles) of some but not other of those contexts, and adds 6 more contexts in which the size matters?
I want to say "When displaying a user profile, If there's more than X units of horizontal space, use the large profile image. If there's more than Y units of vertical space show their bio, trimmed to length but avoiding widow sentences and followed by ellipsis. If there's very little room at all, just show their user name."
I know what I want and I can describe it simply and in a way that a machine could implement, but using today's tools it will take significant developer (human) effort (which typically isn't within my client's priorities and ultimately gets neglected).
If it shows up in 18 places I bet you there will be two different contexts with the same container size, but different looks, and element queries won't help you at this point. You'll still need to tailor your CSS classes for different contexts.
Don't think of it as an improvement or replacement, but as an addition.
If you create an account at Stipple.com and log in, you'll see an example of what I'm talking about (disclosure: I'm an engineer at Stipple).
You could set up size points for an Element like this (mobile first approach) :
$(".testimonials").when-min-width(400px, "medium").when-min-width(800px, "large");
Then you're CSS could look like this :
.testimonials{ // do basic stuff, and small display stuff }
.testimonials.medium{ // do medium display stuff }
.testimonials.large{ // do large display stuff }
Hmm. Maybe I'll build it.
"Javascript is relatively unreliable on many of those devices"
AFAIK it's reasonable to argue that just as Javscript can be unreliable, even non-existent, on many devices, so can CSS media queries. I think it's fair to say that media queries are still a "modern" browser feature. http://caniuse.com/css-mediaqueries
"what's worse, you don't want to force a jquery call just to do..."
Agreed - jquery is too large just for this. That's why I said "javascript/jquery". The jquery like syntax used was for simplicity. But in truth any simple selector engine would do the job. Sizzle for example, or even a home-grown one.
"...something that's actively supported by CSS3"
But that's the point OP was making isn't it? AFAIK, CSS3 @media queries do not support element level querying.
An obvious example of this is transitions. If you have CSS3 transitions you can trigger them with a class name change instead of using jquery's animation code. When you can do that you don't need jquery or other library at all. Unless you have simply awful HTML that requires an advanced selector engine, such as Sizzle as you state.
But as you point out, if the devices listed have unreliable support of javascript then chances are it has unreliable support of CSS3.
I don't understand the argument against building a shim as a proof of concept though. What's wrong with building the example to see if it becomes popular in traditional uses of CSS before pushing it as a standard? Don't bother since it might not work on TVs because of lack of proper javascript support?
If you could only rely on your parent, that would also be problematic - the size of a component would be dependent on its chain of parents. If you were reusing the same component within further containers, say 3 different pages, you might want two to look the same despite a size difference, and element queries don't help you anymore. You just need a .testimonial.compact class, have slitghtly different media targeting, and now you have two types of testimonials that you can use on further pages.
Element queries could also easily create strange loops that cause the threshold to be crossed recursively, if the parent bases its width on the child. This is the case with inline-block elements and the property-which-must-not-be-named.
But the way that technique is implemented is actually very similar to what you're describing: the CSS causes the selected element to examine some of its DOM properties and conditionally apply styles on a per-property basis.
Maybe this is another great old IE quirk that needs some W3 loving?
[0] http://msdn.microsoft.com/en-us/library/ms537634(v=vs.85).as... [1] http://www.svendtofte.com/stylesheets/reflections-on-max-wid...
With media queries, it's essentially impossible to let users choose their format experience.
Element queries would be nice, but aren't we essentially doing that if we take the idea of the previous approach and apply to more high level elements?
If we create media queries on a per element basis we are essentially achieving the same thing. In that sense media queries are a superset of your proposed solution. It would make for a nice short hand though.
In fact the concept itself of querying the whole window to understand the dimension a portion of it will occupy... well it's strange.
At the same time, have you considered the implications of such a structure? A local media query could change the queried properties. Dangerously recursive.
In fact you COULD reach what you want using seamless iframes. I tinkered my head with such an option sometimes.
I can create similar self contained components in JSF and several other languages (frameworks), so I'm wondering if the problem is the author's development technique.
You would still need to use different CSS in the two cases mentioned, so it would be two different packaged components in GWT, two different Views. Maybe interiting from one another, but certainly far FAR more lines of code than a conditional / "modifier" CSS class. .testimonial.compact vs just a normal .testimonial, for instance.
This is definitely one to grow on.
Personally, for reviewing Google Analytics I just prefer making my web apps & sites responsive. Though responsive can take quite of bit of time.
You can actually use media queries to link separate style sheets: http://www.w3.org/TR/css3-mediaqueries/#media0
I blogged about the same issue not long ago: http://pxlz.me/44