How to do mobile first with Bourbon Neat Framework - css

I've been using bourbon neat to do a desktop first layout that worked fine.
However, I would like to do a mobile first versions, starting with mobile and working my way up. The default grid is 12 columns and for mobile I usually use a grid of 4. I tried changine my grid to 4 and scaling up to 12 but this didn't work.
Is there a better way to do mobile first other than creating the standard desktop layout, then putting a mobile media query into each CSS selector and starting with the mobile version and building up the way?

You should create new breakpoints with the new-breakpoint mixin from Neat. But instead of using max-width like they do in their examples, you can use min-width.
For example:
#import "bourbon/bourbon";
#import "neat/neat";
$mobile: new-breakpoint(min-width 0px 4);
$tablet: new-breakpoint(min-width 760px 8);
.main {
background: grey;
#include media( $mobile ) {
#include span-columns(4);
background: white;
}
#include media( $tablet ) {
#include span-columns(8);
background: black;
color: white;
}
}
In the example .main will have a white background and consist out of 4 columns. When the viewport is at least 760 pixels width, it will get a black background and span 8 columns.

To expand on Jorn's answer... you also need to set the $grid-columns variable to the mobile width number, as opposed to the desktop number that it is set as a default. This is what the _grid_settings.scss file looks like for a project I'm currently working on:
#import "../neat/neat-helpers";
// Neat Overrides
$column: golden-ratio(1em, 3);
$gutter: golden-ratio(1em, 1);
$grid-columns: 6;
$max-width: em(1280);
// Neat Breakpoints
$mobile-large-screen: em(480);
$tablet-small-screen: em(560);
$medium-screen: em(640);
$medium-large-screen: em(750);
$large-screen: em(860);
$x-large-screen: em(970);
$xx-large-screen: em(1088);
$super-large-screen: em(1280);
$mobile-large-screen-up: new-breakpoint(min-width $mobile-large-screen 6);
$tablet-small-screen-up: new-breakpoint(min-width $tablet-small-screen 6);
$medium-screen-up: new-breakpoint(min-width $medium-screen 12);
$medium-large-screen-up: new-breakpoint(min-width $medium-large-screen 12);
$large-screen-up: new-breakpoint(min-width $large-screen 12);
$x-large-screen-up: new-breakpoint(min-width $x-large-screen 12);
$xx-large-screen-up: new-breakpoint(min-width $xx-large-screen 12);
$super-large-screen-up: new-breakpoint(min-width $super-large-screen 12);
You can see I've created a lot of new breakpoints and I'm using 6 cols at mobile width as opposed to 4 in the original Neat settings (necessary for what I have going on in my project). You should tailor these settings to work for your own project. The takeaway though is that I'm overriding the $grid-columns variable and then creating my new breakpoints. Also, be sure to import your _grid_setting.scss BEFORE Neat...
#import "bourbon/bourbon";
#import "grid_settings";
#import "neat/neat";

I would scope out Chasers by Kenneth Ormandy. It's a little omega-reset(xn) include passing "xn" from the previous media-query's omega(xn). He provides plenty of documentation on the github repo and you can easily install it with Bower or NPM.

Related

Susy change flow from rtl to ltr if a class exists

I need the $susy variable to change from rtl to ltr if an ar class exists in body. I need to do it to support multi lingual on my site,below is the code for the same
.page-container {
background-color: red;
#include container($susy);
#include susy-breakpoint($medium) {
background-color: yellow;
#include container($susy-medium);
}
#include susy-breakpoint($large) {
background-color: lightgreen;
#include container($susy-large);
}
&.ar {
//change flow to rtl
}
}
$medium: 768px; //tab
$large: 1024px; //desktop
//susy grid params small
$column-numbers-small: 6;
$column-width-small: 40px;
$column-gutter-small: 16px;
$available-width-small: 336px;
//susy grid params medium
$column-numbers-medium: 12;
$column-width-medium: 42px;
$column-gutter-medium: 20px;
$available-width-medium: 744px;
//susy grid params large
$column-numbers-large: 12;
$column-width-large: 86px;
$column-gutter-large: 24px;
$available-width-large: 1320px;
$susy: (
container: $available-width-small,
container-position: center,
columns: $column-numbers-small,
math: fluid,
output: isolate,
gutter-position: split,
gutters: $column-gutter-small/$column-width-small,
);
$susy-medium: (
container: $available-width-medium,
container-position: center,
columns: $column-numbers-medium,
math: fluid,
output: isolate,
gutter-position: split,
gutters: $column-gutter-medium/$column-width-medium,
);
$susy-large: (
container: $available-width-large,
container-position: center,
columns: $column-numbers-large,
math: fluid,
output: isolate,
gutter-position: split,
gutters: $column-gutter-large/$column-width-large,
);
$susy-large-ar: (
flow: rtl,
container: $available-width-large,
container-position: center,
columns: $column-numbers-large,
math: fluid,
output: isolate,
gutter-position: split,
gutters: $column-gutter-large/$column-width-large,
);
Can somebody please suggest how to override this flow direction dynamically.
This isn't possible in the way you've currently framed it. One of the major limitations of using a preprocessor (like Sass) is that variables do not have access to the DOM. That means there is no way to change a variable based on a body class. There are a few ways to work around that, but none of them are simple and fully dynamic. Basically, you have to create duplicate styles for each direction.
Option 1: Separate Output CSS
Some people do that with separate ltr and rtl stylesheets. Rather than adding a class to flip direction, you load a different stylesheet. To make the Sass work, create two sass files (e.g ltr.scss and rtl.scss) – and set them up like this:
// set your flow at the top of each document…
$flow: (flow: rtl);
Then put all your actual styles in Sass "partials" (_filename). One of those partials can merge the new flow into your existing variables:
// Merge flow with other Susy settings…
$susy: map-merge($susy, $flow);
$susy-medium: map-merge($susy-medium, $flow); // etc…
Then import your partials into each document. This way you can compile the same code, with different variables…
#import 'flow-setup';
#import 'actual-style-partials';
Option 2: Inline Duplication
The other option I've seen people use to create a class system (rather than split stylesheets) gets kinda bulky in your code:
.element {
#include span(3 of 12);
.rtl & {
#include span(3 of 12 rtl);
}
}
You can write a mixin to do that for you automatically:
#mixin flow-span($details) {
#include span($details);
$rtl: append($details, rtl);
.rtl & {
#include span($rtl);
}
}
You would have to do the same thing for every Susy mixin you use.
Sorry neither option is simple, but that's about the best you can do in a pre-processor.

Bourbon neat not behaving as expected in my mobile-first setup

I'm using bourbon neat for the first time and it's not behaving exactly how I would expect - which probably means I've set things up wrong.
I'm developing mobile-first, so I would expect my layout to remain the same between my desktop breakpoint and my larger breakpoint (for the styles to cascade to the next breakpoint). However, my layout jumps back to the mobile layout unless I redefine the styles again in the larger breakpoint.
Here is how I've defined my breakpoints in my base/_grid-settings.scss:
// Neat Overrides
$grid-columns: 4;
$max-width: 90%;
// Breakpoints
$first-breakpoint-value: 641px;
$second-breakpoint-value: 1024px;
$third-breakpoint-value: 1440px;
$fourth-breakpoint-value: 1920px;
$tablet: new-breakpoint(min-width em($first-breakpoint-value) max-width em($second-breakpoint-value) 8 );
$desktop: new-breakpoint(min-width em($second-breakpoint-value + 1) max-width em($third-breakpoint-value) 12 );
$large: new-breakpoint(min-width em($third-breakpoint-value + 1) max-width em($fourth-breakpoint-value) 12 );
$xlarge: new-breakpoint(min-width em($fourth-breakpoint-value +1) 12 );
Then my element looks like this:
.container {
#include outer-container;
.swatch {
// mobile styles (here my swatch has a width of 100%)
border: 1px solid #000;
text-align: center;
margin-bottom: $gutter;
//MEDIA QUERIES
#include media($tablet) {
#include span-columns(4);
#include omega(2n);
}
#include media($desktop) {
#include span-columns(3);
#include omega(4n);
padding: 2em -0px;
}
#include media($large) { }
#include media($xlarge) { }
}
}
Now I was expecting the styles from my $desktop media query to cascade all the way up to the $xlarge media query, however currently the .swatch element jumps back to being 100% of it's parent container at the $large and $xlarge breakpoints.
What have I done wrong?
I shouldn't need to keep repeating the same code for every breakpoint if I want the styles to cascade up.
You are defining a media query range, which is why it is snapping back to the mobile view in between.
Remove the max value from your breakpoint and the values will cascade up to desktop.
Im not too familiar with neat but the following should work:
$tablet: new-breakpoint(min-width em($first-breakpoint-value) max-width em($second-breakpoint-value) 8 );
becomes:
$tablet: new-breakpoint(min-width em($first-breakpoint-value) 8);
Hope this helps you or any one else reading this post, I had a similar issue and found this handy omega reset mixin.
http://www.joshfry.me/blog/2013/05/13/omega-reset-for-bourbon-neat
Thanks #nickspiel - that was half the answer! You are correct, adding min-with only breakpoints is the way to get the styles to cascade up the breakpoints. Doing that with Bourbon Neat and an element that is using omega is a bit more tricky.
It seems that I have 2 choices:
Use media query splitting, as per the docs, but then you need to set styles for every breakpoint.
Use your suggestion of min-width breakpoints in conjunction with an Omega reset - I'm going with this option.

Change `$column-width` at breakpoint, but not number of columns

Most Susy examples I've seen seem to handle situations where the amount of columns changes at a given breakpoint, i.e.:
$total-columns: 4;
$large: 12;
// code based on 4 columns
#include at-breakpoint($large) {
// code based on 12 columns
}
But what about when you want the number of columns to remain the same, but (for example) just change the column width? Like this:
$total-columns: 12;
$column-width: 3em;
$large: 64em;
$large-column-width: 3.75em;
#include at-breakpoint($large) {
$column-width: $large-column-width; // automagically changes previously declared column-widths.
}
I would want anything using columns() or span-columns() before the breakpoint to automatically adjust their values to the new column-width without having to redeclare them.
So...
foo { #include span-columns(4, $total-columns); }
would not change at the breakpoint, but the width of the columns would, automatically.
Is this possible?
Susy 2 solves this problem using the new susy-breakpoint with a more powerful shorthand syntax. But the Susy 1 approach isn't much more complex. The at-breakpoint mixin is a simple wrapper for two actions:
Set up a media-query.
Change the global Susy settings inside that media-query block.
I recommend downloading Breakpoint (or another plugin like it) to handle the media-query side of things, but you can also do it by hand. Susy provides a mixin to handle the second part (with-grid-settings). If you put those two together, you have a more powerful version of at-breakpoint.
$large: 64em;
$large-column-width: 3.75em;
#media (min-width: $large) {
#include with-grid-settings($column-width: $large-column-width) {
// new column-width applied to code in here.
}
}

Combining layout breakpoints in Compass Susy?

I am just atarting to use Susy
I have defined my layouts, I needed to start with the desktop version and add 2 more: one for tablets and one for phones:
$total-columns : 12;
$column-width : 4em;
$gutter-width : 1.4em;
$grid-padding : $gutter-width;
$phone: 4 35em;
$tablet: 35em 8 70em;
Seems to be working. My issues arise when there's a change I need to make to something that should appear in the desktop but not in EITHER of the other 2, I find myself repeating myself:
#my-div {
#include span-columns(3 omega,7);
#include at-breakpoint($tablet) {
display:none;
}
#include at-breakpoint($phone) {
display:none;
}
}
How can I simplify this?
In that instance, you don't need susy, you just need a basic CSS media-query with max-width 70em. the only reason for at-breakpoint is to get a media-query/layout change combination. Alternatly, add '$small: 8 70em;' and use that.

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