Is it possible to use Foundation semantic grid mixins inside mediaqueries? - css

I've made a small example grid with the foundation framework(http://foundation.zurb.com/). The grid is made out of four floating elements on a desktop mode(_setting, $rowWidth 1140px)
*markup
<div id="container">
<div id="main">
<div id="column">
*scss
#container{
#include outerRow();
}
.column{
#include column(3);
}
Above mixins based on these sources: http://foundation.zurb.com/docs/sass-mixins.php
Now I want to change the column structure when the example will be viewed on a tablet in portrait mode. I've made something like this:
#media screen and (min-width: 768px) and (orientation: portrait) {
#container{
#include outerRow();
}
.column{
#include column(6);
}
}
The following error occurs:
> DEPRECATION WARNING on line 21 of /Library/Ruby/Gems/1.8/gems/zurb-foundation-3.2.3/scss/foundation/mixins/_semantic-grid.scss:
> #extending an outer selector from within #media is deprecated.
> You may only #extend selectors within the same directive.
> This will be an error in Sass 3.3.
> It can only work once #extend is supported natively in the browser.
Can anybody tell me what the working method is to re-define the column structure for each different media query in a foundation based project?

Generally speaking, all you should need to do is redefine the extend mixins like %clearfix within your media query. If those classes are defined within another file, importing the file would also work (provided you aren't placing it within some sort of control block, like an if/else statement).
Looking at the source of the project, what you're looking to do probably shouldn't be done that way (see: https://github.com/zurb/foundation/blob/master/scss/foundation/mixins/_semantic-grid.scss)
Both of the mixins referenced in your sample code generate their own media queries, so avoid invoking them twice on the same element or you'll end up with a lot of duplicate/unused CSS. Instead, just overwrite the properties that actually need modifying:
.exampleA {
#include outerRow();
#media screen and (min-width: 768px) and (orientation: portrait) {
// do not #include outerRow() again here!
// these are the only properties that are variable in the outerRow() mixin:
width: $tabletWidth;
min-width: $tabletMinWidth;
}
}
The other thing you need to realize is that once you've defined your $totalColumns, you're stuck with it when using the column mixin (see: https://github.com/zurb/foundation/blob/master/scss/foundation/mixins/_semantic-grid.scss#L64 and https://github.com/zurb/foundation/blob/master/scss/foundation/mixins/_semantic-grid.scss#L19). You can't have 6 total columns by default and then 4 for your tablet. If you need to be able to this, you could simply run the gridCalc() function yourself:
.exampleB {
#include column(6);
#media screen and (min-width: 768px) and (orientation: portrait) {
width: gridCalc(2, 6); // columns, totalColumns
}
}
If you're ok with the number of $totalColumns for your media query, pass $totalColumns as the 2nd argument.

Related

sass load mixin conditionally based on media query

Is it possibile to load/unload mixins based on a media query? Something like this:
#if #media (min-width: 768px) {
#include mixin1;
}
#else {
#include mixin2;
}
if the condition is met, mixin2 should not be loaded at all.
Not really, the sass compiles server side, not knowing the clients screen size. The compiled css will be used for all screen widths, thus:
#include mixin2;
#media (min-width: 768px) {
#include mixin1;
}

What is the purpose of including "all" in #media rules?

So you see a lot of code examples do something like
#media all and (max-width:640px) {
div {
background-color:red;
}
}
Now afaik, the keywords "all" and "screen" and some others are for selecting the device type this applies to and the line is just supposed to provide a boolean output.
Since "all" applies to every device, one would imagine that its always 1 and (1 && x) always equals x so "all and" should make no difference whatsoever.
I tried out
#media (max-width:640px) {
div {
background-color:red;
}
}
and at least my browsers agree. Is there anything else I should know about?
See the spec: https://www.w3.org/TR/css3-mediaqueries/
The ‘print’ and ‘screen’ media types are defined in HTML4. The complete list of media types in HTML4 is: ‘aural’, ‘braille’, ‘handheld’, ‘print’, ‘projection’, ‘screen’, ‘tty’, ‘tv’. CSS2 defines the same list, deprecates ‘aural’ and adds ‘embossed’ and ‘speech’. Also, ‘all’ is used to indicate that the style sheet applies to all media types.
...
A shorthand syntax is offered for media queries that apply to all media types; the keyword ‘all’ can be left out (along with the trailing ‘and’). I.e. if the media type is not explicitly given it is ‘all’.
/* I.e. these are identical: */
#media all and (min-width:500px) { … }
#media (min-width:500px) { … }
/* As are these: */
#media (orientation: portrait) { … }
#media all and (orientation: portrait) { … }
In addition, the following media types: 'tty', 'tv', 'projection', 'handheld', 'braille', 'embossed', 'aural' have been deprecated in Media Queries Level 4.
all refers to: all media type devices, print: used for printing, screen: used for desktop screens, mobiles, tablets etc and speech: used for screen-readers that "reads" the page out loud.
In your case where you have specified media type as all, you can try printing the page by right clicking. The printed page will have all the styles applied in short it will exactly look the same.
Now take another example where you specify the media type as screen. If you try to print the page you will not see all the styles getting applied to the page as the styles were defined for screen alone.
If one does not specify all in media query it is by default taken as all.
#media screen {
div {
color: blue;
}
.print{
display: none;
}
}
#media print and (min-width: 200px){
div{
color: tomato;
}
div.not('.example'){
display:none !important;
}
.print{
display: block;
}
}
<div class="example">
<div>Try printing me. See if this blue color appears while printing</div>
<div class="print">I am only visible while printing.</div>
</div>

Send properties as argument for mixin

I'd like to break out all of my Media-queries and pass the CSS properties as arguments instead.
.bp1(#css){
#media (max-width: 959px){
#css
}
}
.bp1(width: 186px;);
Unfortunately, this wont work and makes the Less fail :(
Starting with Less v1.7.0, it is possible to pass detached rulesets as parameter to a mixin.
Quoting Less Website:
Detached ruleset is a group of CSS properties, nested rulesets, media declarations or anything else stored in a variable. You can include it into a ruleset or another structure and all its properties are going to be copied there. You can also use it as a mixin argument and pass it around as any other variable.
Note that the properties that form a part of the ruleset must be enclosed within {}. Also, parentheses (()) are a must after the detached ruleset call (like #css();). Without the parentheses at the end, the call would not work.
.bp1(#css){
#media (max-width: 959px){
div{
#css(); // detached ruleset call
}
}
}
.bp1({width: 186px;}); // passing ruleset to mixin
Compiled Output:
#media (max-width: 959px) {
div {
width: 186px;
}
}
Alternately, the ruleset can be assigned to a variable which in-turn can be passed in the mixin call like below. This would also produce the same output when compiled.
.bp1(#css){
#media (max-width: 959px){
div{
#css(); // detached ruleset call
}
}
}
#ruleset: {width: 186px;};
.bp1(#ruleset);
Using this feature, it is possible to pass not only group of properties but also the selectors along with it (like shown below):
.bp1(#css){
#media (max-width: 959px){
#css(); // detached ruleset call
}
}
.bp1({
div{width: 186px;}
div#header{color: gold;}
});
Compiled Output:
#media (max-width: 959px) {
div {
width: 186px;
}
div#header {
color: gold;
}
}
The LESS documentation about mixins says: "Mixins allow you to embed all the properties of a class into another class by simply including the class name as one of its properties. It’s just like variables, but for whole classes. Mixins can also behave like functions, and take arguments, as seen in the example bellow."
You can't have anything but css properties and their values, either stated or represented by a variable, in a mixin. So what you're trying to do is invalid.

Where to put CSS3 media queries?

I am having a philosophical debate with myself over the best place to put media queries within style sheets. I am attempting to structure my CSS modularly (like OOCSS or SMACSS, etc). Given that context, I see two choices:
Put all media queries together in a separate stylesheet or section of the main stylesheet.
Put media queries below their base counterparts. For example, if I have a module called "news-item", I could put any necessary media query styles right below the definition of that module.
I am leaning towards the latter, but it would mean I'd have many more separate media queries (separate ones for each logical block of CSS requiring a responsive adjustment).
Any thoughts on this?
How about using media queries just to load device specific stylesheets
like:
#import url(mydevice.css) this and (that);
or:
<link rel="stylesheet" media="only this and (that)" href="mydevice.css" />
...if you're looking at the device specific adjustments as a kind of "subthemes" to a main layout (just overwriting some properties), this would make sense to me, too.
Approach #2 works better for me.
When I was a newbie, I was using Approach #1 - I was writing my media queries together (at the bottom of my stylesheet or in another file).
.header { ... }
.news-item { ... }
.footer { ... }
/**
* ...
*
* bla bla, imagine a huge amount of styles here
*
* ...
*/
/** All style tweaks for screens < 1024px */
#media screen and (max-width: 1024px) {
.header { ... }
.news-item { ... }
}
This approach has a few downsides. Based on my experience, the most notable one is that the maintainability is a hard. The main reason: .news-item logic is spread across multiple unrelated lines of CSS.
Later on, naturally, I decided to keep the related styles together. Approach #2:
/** Header's styles and media queries */
.header {
...
}
#media screen and (max-width: 1024px) {
.header { ... }
}
#media screen and (max-width: 720px) {
.header { ... }
}
/** News-item's styles and media queries */
.news-item {
...
}
#media screen and (max-width: 1024px) {
.news-item { ... }
}
#media screen and (max-width: 720px) {
.news-item { ... }
}
/** ... and so on */
However, in this approach, repeating media queries max-width values all-around doesn’t look maintainable enough. I solved this issue by using a CSS pre-processor (like SASS) that allows me to replace all them with variables and define them once.
To boost up the maintainability and to make these definitions a lot more elegant I started to use an abstraction on top of the Media Queries.
If you're interested in more details, please read on my blog post :-)
With Sass it's easier to use the media queries directly below the counterparts. But if your CSS is well commented in your modules, I don't see a problem to put the queries bellow since that would be easy to find.
You'll end up writing a little more code retyping the queries, but not a big deal.
May be you can try css variables, which is native support reuse your css!
:root {
--main-color: #F06D06;
}
.main-header {
color: var(--main-color);
}
.main-footer {
background-color: var(--main-color);
}
https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables
https://developers.google.com/web/updates/2016/02/css-variables-why-should-you-care
https://css-tricks.com/difference-between-types-of-css-variables/

SASS 3.2 Media Queries and Internet Explorer Support

I recently implemented this technique with SASS 3.2 using #content blocks on a project I've been working on, and I've just gotten to the point where I need to include support for older browsers such as IE7 and 8.
Example:
.overview {
padding: 0 0 19px;
#include respond-to(medium-screens) {
padding-top: 19px;
} //medium-screens
#include respond-to(wide-screens) {
padding-top: 19px;
} //medium-screens
}
They both don't support media queries, and I've often handled this in the past by serving up all styles to these browsers when I had my media queries separated into separate partial files such as _320.scss, _480.scss and in my IE stylesheet loading them like so:
#import 320.scss;
#import 480.scss;
etc.
Which would load all styles, and always assign IE7 - 8 a 940px (or whatever the max width is) layout and styles. By nesting styles in SASS 3.2 inline like this, it eliminates the need for separate partial stylesheets, but totally screws up how I load styles for IE.
Any ideas or solutions on how to combat this? I could use a polyfill such as respond.js to force IE to use media queries, but would prefer to just serve up a non-flexible site to IE.
Any ideas on either how to best organize these files, or a better solution?
You can generate a separate stylesheet for IE<9 that contains everything your normal sheet has, but with flattened media queries based on a set width.
Full explanation here http://jakearchibald.github.com/sass-ie/, but basically you have this mixin:
$fix-mqs: false !default;
#mixin respond-min($width) {
// If we're outputting for a fixed media query set...
#if $fix-mqs {
// ...and if we should apply these rules...
#if $fix-mqs >= $width {
// ...output the content the user gave us.
#content;
}
}
#else {
// Otherwise, output it using a regular media query
#media screen and (min-width: $width) {
#content;
}
}
}
Which you'd use like this:
#include respond-min(45em) {
float: left;
width: 70%;
}
This would be inside all.scss, which would compile down to all.css with media queries. However, you'd also have an additional file, all-old-ie.scss:
$fix-mqs: 65em;
#import 'all';
That simply imports all, but flattens media query blocks given a fake width of 65em.
I use LESS for a lot of my work, but on larger projects, with many people working across files, I don't like using breakpoint files, such as 1024.less.
My and my team use a modular approach, such as header.less which contains all the code for just the header, including the associated breakpoints.
To get round IE problems (we work in a corporate environment), I use this approach:
#media screen\9, screen and (min-width: 40em) {
/* Media queries here */
}
The code inside the media query is always executed by IE7 and less. IE9 and above obeys the media queries like a proper browser should. The problem is IE8. To solve this, you need to make it behave like IE7
X-UA-Compatible "IE=7,IE=9,IE=edge"
I've found this doesn't always work if set in the metatags in the HTML, so set it using the server headers.
See the gist here:
https://gist.github.com/thefella/9888963
Making IE8 act like IE7 isn't a solution that works for everyone, but it suits my needs.
Jake Archibald has the best technique I've seen to date for achieving this. This technique automatically creates a separate stylesheet for IE, with all the same styles inside of your media queries but without the media query itself.
I also campaigned to get this technique built into the popular breakpoint extension for Sass, if you're interested in using that!
If you wanted to keep everything under one roof and only have a single http request for your older browser visitors you could do something like this
Setting up your initial respondto mixin
// initial variables set-up
$doc-font-size: 16;
$doc-line-height: 24;
// media query mixin (min-width only)
#mixin breakpoint($point) {
#media (min-width: $point / $doc-font-size +em) { #content; }
}
this will create a min-width media query and output your px value ($point) as an em value.
From this you'd need to create this mixin
#mixin rwdIE($name, $wrapper-class, $IE: true) {
#if $IE == true {
.lt-ie9 .#{$wrapper-class} {
#content;
}
.#{$wrapper-class} {
#include breakpoint($name) {
#content;
}
}
}
#else if $IE == false {
.#{$wrapper-class} {
#include breakpoint($name) {
#content;
}
}
}
}
Here if you pass a piece of Sass(SCSS) like this
#include rwdIE(456, test) {
background-color: #d13400;
}
it will return this code
.lt-ie9 .test {
background-color: #d13400;
}
#media (min-width: 28.5em) {
.test {
background-color: #d13400;
}
}
This will give you the you the IE and 'new browser' CSS in one file. If you write -
#include rwdIE(456, test, false) {
background-color: #d13400;
}
You will get -
#media (min-width: 28.5em) {
.test {
background-color: #d13400;
}
}
I hope this helps, I've got this on a codepen here too - http://codepen.io/sturobson/pen/CzGuI
There is a CSS3 Mixin I use that has a variable for IE filters. You could do something similar by having a global variable, $forIE or something, wrap the media query mixin within an if and then generate the stylesheet with or w/o the queries.
#if $forIE == 0 {
// Media Query Mixin
}
Or use the #if to import a 3rd scss (_forIE.scss?) that will override things with your IE specific styles.

Resources