I found this method to easily add #media block using mixin:
#mixin phone() {
#media only screen and (max-width: 480px) {
#content;
}
}
To use it, just simply type something like this:
p {
#include phone { ... }
span {
#include phone { ... }
}
}
But the problem lies in the real CSS output:
#media only screen and (max-width: 480px) {
p { ... }
}
#media only screen and (max-width: 480px) {
p span { ... }
}
It duplicates the #media ... part which will bloat the CSS.
Is there a way to make the mixin act like placeholder? So it will combine all #content and put it under the same #media ... block.
So the result will be like
#media only screen and (max-width: 480px) {
p { ... }
p span { ... }
}
I know I can just put the #include phone at the end of the file and write all the necessary styles in that block.
But writing the media-query style right besides the original one makes it easier to read and organize.
Thanks
Sass does not have that functionality at this time. Your only option is to manually group your styles within a single media query (or use a 3rd party CSS compressor that has that functionality).
https://github.com/nex3/sass/issues/116
You just have to adjust your nesting. Because the mixin will place all your content within the media-query, you only want to use the mixin once and place all relevant styles within it (to avoid multiple media-queries).
#include phone {
p {
span { ... }
}
}
If you are trying to combine styles for <p> and <span> for various media-queries, you will inevitably end up with some separation of styles, either in your preprocessed or output code.
For example:
p {
...
span { ... }
#include phone {
...
span { ... }
}
}
Hope that helps. Even if you end up with output that feels 'less efficient', it shouldn't actually slow down browser rendering, so I'd say prioritize writing code that feels maintainable to develop.
SASS can not combine extends with media queries**, so duplicate media queries are currently inevitable when you adopt this code style.
You could structure your code with media queries at the top level (i. e. group code by media queries), but this is generally a bad idea. Eric Meyer, one of the CSS gurus here, says (and many other front end enthusiasts would agree) that you should never do that. I have tried this approach myself on one project and i confirm that the larger your project gets, the more painful this code structure appears. SMACSS and other code structure methodologies also advise against it.
Where this code structure is widely used is in CMS base themes (theme templates aka starter kits). But they are aimed to allow users quickly override default styles rather than build from scratch.
The matter is that the duplicate media queries don't really matter. Though #cimmanon might not agree with me, only the readabiliy and maintainability of your source code (SASS) should matter, because every modern web server provides compression (gzip) for CSS code which is read only by machine.
Of course, there are many ways of ruining your CSS by making it unreasanably huge. Using a non-semantic CSS framework is one of them. Wisely applying a lot of local media query blocks is not.
Related
I've set up some variables in SASS as follows:
// fundamental layout variables
$raw-layout-var-1: 60px;
$raw-layout-var-2: 200px;
// calculated layout variables
$calc-layout-var-1: #{$raw-layout-var-1} + #{$raw-layout-var-2};
I am attempting to use these variables with media queries so I can do something like the following, and have the calculated variables and the rest of the stylesheet update when the relevant criteria are met. I would like to be able to override the fundamental or calculated variables as I need.
#media only screen and (min-height: 500px) {
$raw-layout-var-1: 120px;
#media only screen and (min-width: 500px) {
$raw-layout-var-2: 100px;
}
Currently I have a workaround where all updates to variables use the !global keyword to update them globally, but this results in a somewhat complex setup where the fundamental variables, calculated variables, and the main css sheet are placed in mixins, to be called in each individual media query:
#mixin reset-raw-vars() {
$raw-layout-var-1: 60px !global;
$raw-layout-var-2: 200px !global;
}
#mixin update-calc-vars() {
$calc-layout-var-1: #{$raw-layout-var-1} + #{$raw-layout-var-2} !global;
}
#mixin add-main() {
div {
width: $calc-layout-var-1;
height: $raw-layout-var-1;
}
}
#media only screen and (min-width: 500px) {
#include reset-raw-vars(); // resets the raw variables in case these were changed globally in a previous media query
// here you can change any fundamental variables you need
#include update-calc-vars(); // recalculates calculated variables
// here you can override how any calculated variables are made
#include add-main(); // update the rest of the stylesheet with new layout
}
Even worse, if I have a pair of media queries such as those shown in the second code block, I have to manually create a hybrid with both min-height and min-width in order to apply both sets of conditions. Clearly this isn't DRY and could get seriously out of control with even slightly complex responsive pages. I can see from Using Sass Variables with CSS3 Media Queries that SASS doesn't have this functionality - is there a better way than I've outlined above?
How can I nest the following in SASS?
.class {
// First styles
}
a.class:visited {
// Second styles
}
I can nest the :visited pseudo class with this, but im not sure how to add the link element?
.class {
// First styles
&:visited {
// Second styles
}
}
I don’t know why you’d want that, adding the a probably just adds unnecesary specificity. If you really need that there’s probably a design flaw somewhere else.
That said, you can make it work using interpolation around the &. However that doesn’t really give you the expected result so you need #at-root as well to make it work.
.class {
// some styles...
#at-root a#{&}:visited {
// ...more styles!
}
}
I don’t think this is the best way of solving your problem though. Using Sass should result in easier maintainable code.
I'm wondering whether Sass provides a way to create custom control directive which is the "#" command like #if or #for.
I want to make media query syntax looks simpler like:
#below 800px {
...
}
#above 480px {
...
}
Currenly I'm using mixin for this which make the code longer:
#mixin below($size) {
#media only screen and (max-width: $size) { #content; }
}
#include below(800px) {
...
}
So does Sass support this custom control? I can't seem to find solution online.
Note: I don't want to modify the source code.
Thanks
No. Sass does not allow you to create custom control directives. You would have to modify the Sass parser if you wish to do so or continue using mixins as you are currently already doing.
I'm using SASS to create a responsive site. At the moment, my code is structured into a number of partials:
Some default colours and sizes
Overall Layout
Partial for each element
As a result of this organisation I'm finding that I'm ending up with the media queries being declared numerous times through the resulting CSS - it just feels messy. As a result I've been working with a few ideas to keep the current structure, but end up with a simpler resulting code.
My idea goes something like this:
A variable contains a list of the partials to #import
A variable contains a list of the media query sizes (always using min-width, therefore this list is nothing more than a string of numbers)
Each partial (_footer.scss, _header.scss) would then contain a #mixin titles something like - content-footer, content-header, etc
Those #mixin's would take a single variable relating to the media-query and output the appropriate code for that condition.
style.scss would #import each partial from the list,
then cycle through each media-size and partial respectively, calling the function and media size.
The above process would result in something like this being effected...
#import 'footer';
#import 'header';
#include content-footer(0);
#include content-header(0);
#include content-footer(320);
#include content-header(320);
#include content-footer(640);
#include content-header(640);
etc..
My question is this - how do I call the dynamically titled #mixin? Something like content-#{$partial} seems like it should work, but doesn't.
I suppose if this doesn't work, then I could re-import the partial each time, but this seems overkill...
#import 'footer';
#include content(0);
#import 'header';
#include content(0);
#import 'footer';
#include content(320);
#import 'header';
#include content(320);
#import 'footer';
#include content(640);
#import 'header';
#include content(640);
Personally I find comfort in declaring media queries at many places throughout the document. It feels object oriented and it's really easy to keep track of what's actually going on. I'm usually interested in editing one module in particular, not the entire layout, so it makes more sense to me.
I have a mixin that looks something like this:
$mq-small: 30em;
$mq-medium: 50em;
$mq-large: 70em;
#mixin mq($size) {
#if $size == small { #media only screen and (min-width: $mq-small) { #content; } }
#else if $size == medium { #media only screen and (min-width: $mq-medium) { #content; } }
#else if $size == large { #media only screen and (min-width: $mq-large) { #content; } }
}
Which allows me to write media queries like this:
.element {
// generic rules
#include mq(medium) {
// size-specific rules
}
}
Which creates this output:
.element {
// generic rules
}
#media only screen and (min-width: 50em) {
.element {
// size-specific rules
}
}
Then, when the project is ready to be deployed, I merge the media queries manually in the output CSS into one place to remove bloat.
It's not perfectly clean, but it's also not necessary and the workflow is awesome. Last I heard, this merging is supposed to happen automatically in future versions of SASS. Perhaps that's just a rumor, though, but it would be nice.
I have a 'responsive' website but there are some links I only want on 'pc browsers' only and not on 'tablet landscape' becasue they link off to flash objects.
So far this is what I have done but it't not a 100% fix as some android tablets such as 'Lenovo think pad' which have a bigger screen.
I am using media queries to make my site responsive and this is what I'm currently using...
#media only screen
and (max-device-width : 1024px)
and (orientation:landscape)
{
header.Site
{
nav.Site > ul > li { line-height: 2 ; }
div.BidSessionCountdown,
a.LiveOnline { display: none; }
}
}
Is there any CSS fixes you can think of?
Thank you in advance
Tash :D
Using media queries isn't really the appropriate technique to detect if flash is supported or not. My suggestion would be to determine this using JavaScript, and assign a class to the body element such as "no-flash". Your JavaScript might look like this:
//Using jQuery here
if(typeof navigator.plugins['Shockwave Flash'] == 'undefined') {
$('body').addClass('no-flash');
}
Then, your CSS could be as follows:
body.no-flash a.LiveOnline {
display:none;
}
Note: The javascript code that checks the navigator plugin comes from Here.
When you are using the orientation:landscape, you have to consider whether the keyboard popup will change the display, once the width size is larger than the height size, the css will consider it as landscape.