OK, we're assuming we have this configuration:
$container-width: 6; // columns width
$break-small: 12; // larger than a smartphone, holds 12 computed columns
$break-medium: 24; // full desktop screen, holds 24 columns
#main {
@include span-columns($container-width, $container-width);
.blog {
background-color: white;
}
}
The min-width is expressed in columns as $break-small, using the Susy at-breakpoint mixin to generate the CSS @media query:
@include at-breakpoint($break-small) {
#main {
// UPDATE OUTER LAYOUT
@include span-columns($break-small - 4, $break-small); // reduce the inner proportion
@include pad(2, 2, $break-small); // 2 columns each side, in $break-small context
}
}
#main {
// OUTER LAYOUT STAYS THE SAME
@include span-columns($container-width, $container-width); // ie, 100%
.blog {
background-color: white;
// ADDED NEW INNER LAYOUT HERE
@include span-columns($container-width - 1, $container-width); // 5 in 6 or 83.3%-ish
}
}
@include at-breakpoint($break-small) {
#main {
// UPDATE OUTER LAYOUT
@include span-columns($break-small - 4, $break-small); // smaller than container width
@include pad(2, 2, $break-small); // more padding
.blog {
background-color: pink;
// FAIL: WE DID NOT UPDATE CHILD LAYOUT HERE ...
}
}
}
At the small breakpoint (eg larger than about a smartphone viewport size), the layout on #main is overridden and the context becomes $break-small (12).
We can say the break-small #main layout is "$break-small minus 4 wide in a context of $break-small."
We still have an inner width of 6 columns ($container-width did not change, #main was overriden by a breakpoint). But now the #main container for .blog is "$break-small (12) minus 4" columns not the original $container-width, 6. Therefore the grid is recalculated incorrectly.
In the first layout it calculates $container-width insde $container-width: 100%.
Which in the second breakpoint becomes something smaller, 8 inside 12. 0.66 percent-ish. Thus the inner container is 83.3%ish inside 0.66 percent-ish now, not inside 100%.
I think this is close to the core of the problem with layouts and breakpoints: your context changes but it does not always properly cascade.
Making things worse, this will actually be pretty close to what you want still. It can be difficult to detect that you have created an error, even when you are using the grid background (percentage rounding issues cause the background to be frequently quite inaccurate!)
Thus main problem I am illustrating so far is: when you update a span-columns in the child elements, you must also update all the calculations in the breakpoints.
-
Change the box model to use IE style. This will not fix the stuff you generate with Sass, it just helps avoid subtracting width on the inner children.
-
Recalculate the inner unit in each one. This means that each breakpoint has a full restatement of many selectors, and is very fragile.
-
As a sneaky academic exercise here, one creative way around the problem is to use breakpoints that are all multiples of 2, and apply child widths and padding that you want to be doubled or halved automatically. This results for instance in the pad(1,1,$container-width) percentage becoming the equivalent of pad(2,2,$break-small). So you can theoretically work with the error that we demonstrated above. Each each breakpoint just double the container width, and if left untouched, child widths will effectively double also.
-
A better solution is to extract only the layout as a mixin and to call it again in the breakpoints. Override the context with the breakpoint width. As each breakpoint min-width is reached, the context is reset to that breakpoint. The columns are then recalculated accurately. Your 83%ish inner column remains 83% even when the container is shrunk, until of course you want to change the proportional balance of the page, which is perfectly awesome if you are doing it on purpose.
Think of the breakpoint is a kind of "atomic context" that applies universally, all at once, and write your layout mixins accordingly.
To rewrite the above, then:
@mixin blog-layout($width, $context) {
#main {
@include span-columns($width, $context);
.blog {
@include span-columns($width - 1, $width); // the good part
}
}
}
#main {
@include blog-layout($container-width, $container-width); // Default mobile layout, 6 in 6 or 100%
.blog {
background-color: white;
}
}
@include at-breakpoint($break-small) {
@include blog-layout($break-small, $break-small);
.blog {
background-color: pink;
}
}
Much better. To optimize, use % placeholder selectors and @extend.