I love nesting my @media query breakpoints. It’s perhaps the most important feature of Sass to me. Maybe I pick a method and do it like this:
.element {
display: grid;
grid-template-columns: 100px 1fr;
@include breakpoint(baby-bear) {
display: block;
}
}
That’s straightforward enough. But what if my element has several sub-elements and the breakpoint affects them as well? There are different approaches, and I’m never quite sure which one I should be doing.
I could duplicate the breakpoint for each child:
.parent {
@include breakpoint(desktop) {
}
.child {
@include breakpoint(desktop) {
}
}
.child-2 {
@include breakpoint(desktop) {
}
}
}
The compiled CSS comes out to something like this:
@media screen and (min-width: 700px) {
.parent {
}
}
@media screen and (min-width: 700px) {
.parent .child {
}
}
@media screen and (min-width: 700px) {
.parent .child-2 {
}
}
Or, I could duplicate the children under the first nested breakpoint:
.parent {
@include breakpoint(desktop) {
.child {
}
.child-2 {
}
}
.child {
}
.child-2 {
}
}
That results in:
@media screen and (min-width: 700px) {
.parent .child {
}
.parent .child-2 {
}
}
.parent .child {
}
.parent .child-2 {
}
Or I could do a combination of the two. Neither of them feels particularly great because of the duplication, but I’m not sure there is a perfect answer here. I err a little more on duplicating the media query, as it seems less error-prone than duplicating selectors.
I do the first approach and rely on a build tool to combine media queries (postcss plugins)
which postcss plugin is that?
I agree, not sure if there’s a perfect answer. I try to minimize the amount of media queries, but find myself not being consistent.
I have the same problem. For me it depends on the number of changes and complexity of the child elements. For complex child elements I nest the media query inside the child. If you only need to change some properties, I group them inside one media query.
I usually (if nesting is unavoidable) do the former one with duplication and optimize the result with some post processor (postcss, webpack loader..etc) to group the same media queries into one entry.. that way u can write reusable blocks and avoid bloating the css file at the same time;)
I still place mine at the end of the file because it’s easier for me to see how the module as a whole changes at a given breakpoint. It’s also much easier to organize when using multiple breakpoints.
Modules rarely get large enough for this approach to be cumbersome and, if you organize your project such that breakpoints all scale in the same direction, it’s very easy to spot spaghetti code.
this redundancy of output has always irked me. it would be great if the processor recognized the media queries repeated throughout the doc and set each once at the end, moving all related content inside.
I usually try to have the breakpoint at the highest-level selector that it might affect in that “tree”, and then put all of the children it affects inside that breakpoint.
It’s a little more error-prone, but it also makes it really clear what changes at different breakpoints all in one place, rather than having to read through each individual selector when looking for something that’s just not quite right on one.
Very useful Gulp tool when nesting a lot: https://github.com/hail2u/node-css-mqpacker
That’s all about OUTPUT, right? I guess I could see how combining the media queries in the output saves some bytes, but my understanding is that gzip makes that negligible and browsers don’t seem to care speed-wise. I’m mostly curious about the authoring experience.
It’s a bit about the size but mostly about authoring, at least in our case. With a lot of code, the second example starts to become tedious to manage quite quickly, especially with a lot of nesting. And we also feel that the first example is more clear and easy to understand what is going on.
The second one, but with the media queries after the styles they’re altering, e.g. the last thing before closing the parent.
I very much like the first approach – it feels nice to nest all styles underneath the selector, rather than duplicate the selector within a media query. This allows you to understand all of the CSS being applied to a selector in a single visual scan.
My mind thinks in terms of selectors: “What does this selector do at such-and-such breakpoint?”
As opposed to: “At such-and-such breakpoint, let’s see if the selector I need is being changed”
I’m sure other folks have different brains, though.
I’m sure other folks have different brains, though.
Absolutely! For me it’s completely opposite – I see it by screens, a bit as if @media opened a css sheet by itself, that’s why I very much prefer the second approach: I would write it exactly like that if I were to author the code by hand.
I’m with you Andy, this is how my brain works too. It’s actually why I moved to using this method in the first place vs having separate scss stylesheets for each breakpoint – it was so hard to find/comprehend all the styles that applied to a specific selector when they were spread out.
Easy solution is to use the postcss plugin mq-packer.
It bundles media queries
I’ve been thinking about the same few hours ago, so was thinking to wrap CSS or Sass variables instead of the nested media queries
For me, the second option is a bit easier to comprehend, and provides a slightly better readability for a new developer to getting up to speed on the project.
Trying to find a specific style at a specific breakpoint is a lot easier when there is only one of each breakpoint per component.
For small tweaks I like nesting multiple media queries, like so:
This lets you easily keep track of what is being modified without having to bouncearound the class looking at all the different media queries.
However, this compiles messily:
Fortunately a minifier set to combine media queries will take care of that:
For me, I prefer using variable and
@media
than using mixinThere’s a postcss plugin to combine media queries.
I use a mobile-first approach, styling the basic stuff first, and having a ‘responsive section’ below, where I make some layout overrides. Gives me the clearest view on the cascade too. You could say large screens are a feature!
I like the first approach, it is like saying “ok, now you at this break do that”.
Plus, when you gzip your css, duplication is a non-issue.
Hey, in your last example. The child div elements will override the CSS in the media query because of the cascade –
I do that exactly in this way. Easier to understand when you have context.
I definitely agree that nesting media queries with scss is the most important feature of the syntax.
I personally go with duplicating the media queries in each child as this makes the most sense to me, all of the styles for that element are kept in the same place. I can’t forget about styling that is separated away half way up the file.
Related to this, I have recently been trying to force myself to not write nested child rules at all. As I have found it can make increased specificity more subtle and I can start getting quite deep selectors in the compiled code that could cause me issues later. Keeping the selectors flat, as with vanilla css, makes this increased specificity much more noticeable to me as I am actually writing out those parent child selectors and it triggers my thought process to access if I actually require that nesting.
I like the second approach as it’s more easy to manage also less duplication, moreover in future they can easily be moved to separate files, based on screen sizes
I tend to do the first way you mentioned. Creates a lot of duplicated mediq queries sadly. I’ve tried the various gulp media query combiners but they seem to provide mixed results for me. Has anyone else tried these? Such as gulp-combine-mq?
I’m really trying to stay away7 from nesting in Sass as much as possible, so I’ll maintain the first approach. Then I’ll follow with low-specificity selectors and apply the breakpoints to them after. I feel this cleans up the Sass and also emulates what the processed CSS will look like, keeping both concerns in mind when authoring.
I only tend to opt for the second one if there’s a lot of changes on that single breakpoint.
Usually I create a breakpoint if the design fits, not just a set of breakpoints. So normally I wrote code as option #1.
I used to use the first method, but on large projects (with a lot of SCSS includes) the compiled CSS file was so much large in KBytes.
I found useful to keep all @media rules on the bottom of every SCSS file I use. So, if I have a .info-box element on its _info-box.scss file, I use to have all @media’s just below .info-box {} block.
That is the way I know where to find everything. And every element/component has its own SCSS file with all breakpoint info.
Personally I use the combine MQ plugin and add breakpoints underneath the children. Because I develop mobile first, it’s easier to read and understand.
https://www.npmjs.com/package/combine-mq
I rarely nest selectors anymore but when I do, I still usually put the media query directly in the selector. This keeps every selector self-contained and handling its own positioning. Even without nesting selectors, the approach is essentially the same because the media queries go into the selector body.
Every project can be different, in my situation, designs always seem to be created with hard breakpoints in mind. With that said, I like to maintain a multi-level folder structure for components, pages, structural templates, etc. There is a folder for global elements, and sub-folders for projects that share the same assets.
With that said, I have a main constructor file which then imports device specific breakpoints (your typical screen sizes) that encompasses all the components, layout elements, etc. in each group. Inside each component folder is an assortment of files defined by width where multiple developers can access the same file and there is no confusion as to where to put breakpoints, because that decision is made by the architecture of the files. Typically there aren’t further sub-breakpoints, though some retina queries may end up making their way in there. It is a little more cumbersome to set up with all the files and imports going on, but this structure has led to many large-scale rapid development projects with great success.
Interesting! I also do the first approach. I think that is more “reasonable” put together all styles that affect one element, as far as possible.
I don’t nest selectors.
.parent {
@include breakpoint(full-hd) {
// …
}
}
.parent__child-1 {
@include breakpoint(full-hd) {
// …
}
}
.parent__child-2 {
@include breakpoint(full-hd) {
// …
}
}
// ————————————–
// And I use pseudo-hrs and headline comments for clarity
I always go for the approach one. It is better and readable so far for me :)
I go with #1 all the time (or at least 99% of the time). Everything happens inside that selector.
I much prefer the first style: define the selector’s base styles, then nest the adjustments for each breakpoint inside of it. It keeps ALL of the styles for a selector in one place, which makes it really easy to see if and how they’re modified at any particular breakpoints.
It’s also cleaner and less error-prone since you’re only defining each selector once. If you use the opposite approach of defining one set of media queries and then duplicating the selectors inside each of them, it’s easier to make a mistake without realizing it (e.g. writing
.parent .child
under one media query but.parent.child
under another).I don’t particularly care what the output looks like since everything ultimately gets minified/concatenated anyway. I’d rather things be more readable and less error-prone for authoring.
Or you could use https://github.com/hail2u/node-css-mqpacker and forget about it.