Bourbon Neat grid-push not working as expected? - sass

I have a really simple issue that seems to be difficult to solve. I want to stick with the normal standard 12 column neat grid, but I want the two .homeSplit divs to take up 5 columns each. I would like the second one(.insights) to get 1col of space in the middle so I gave it a grid-push(1). When it gets to mobile sizes, I want each of these divs to take up the full 12 columns and stack on top of each other. The issue is that once I get down to mobile size, that 1col space I assigned with grid-push(1) is persisting and I can't figure out how to get rid of it.
CSS/SASS:
.homeSplit {
position: relative;
#include grid-column(5);
&.news {
.post {
margin-bottom: 26px;
}
}
&.insights {
#include grid-push(1);
padding-left: 30px;
z-index: 999;
.post {
margin-bottom: 26px;
}
}
}
#media only screen and (max-width: 959px) {
.homeSplit {
#include grid-column(12);
&.insights {
#include grid-push(0);
}
}
}
I have tried grid-push(-1) as well but it goes too far. Am I misunderstanding how to use Neat? Pulling my hair out over here.

The best path here would be to use the grid-media() mixin to have a series of grids. Here is an example of what that would look like (with some of the extraneous code removed.
Also, neat by default favors min-width over max-width in media queries. based on your layout, min-width makes things a lot easier.
$my-desktop-grid: (
media: 959px,
);
.homeSplit {
#include grid-column(); // default's to 12 here
#include grid-media($my-desktop-grid) {
#include grid-column(5);
&.insights {
#include grid-push(1);
}
}
}
I've created a codepen as an example so you can see what this looks like in action.
https://codepen.io/whmii/pen/aVvqma

Option 1: the nesting is wrong.
In looking at the example above the #media declaration is nested within the .homeSplit block, but then .homeSplit is declared again w/in #media. However the code you have above would likely not run and would error out, so I'm going to assume there was something lost in translation when it was copped and pasted in to your question.
Option 2: grid-push wants false or just to be empty.
grid-push(0) isn't really a thing but in sass 0 may == false so you can try the following:
.homeSplit {
position: relative;
#include grid-column(5);
&.news {
.post {
margin-bottom: 26px;
}
}
&.insights {
#include grid-push(1);
padding-left: 30px;
z-index: 999;
.post {
margin-bottom: 26px;
}
}
#media only screen and (max-width: 959px) {
#include grid-column(12);
&.insights {
#include grid-push(); // 'false' is the default here
}
}
}
Note: I also cleaned up some of the nesting at the bottom
Im going to add a second answer that shows how to do this using the grid-media mixin.

Related

check if the parent has a specific class on it

This is the usual list where one of the items is .open
for this I want to check if the parent (in this case is .item but its not relevant i think) has a specific class.
I've tried > but it doesnt seem to work.
Essentially how to put this:
&.open .info {
display: none;
}
&.open .inner-info {
display: flex;
}
inside of the their specific classes:
.info {
display: flex;
/* some other stuff */
}
.inner-info {
display: none;
/* some other stuff */
}
all of this is inside an .item{} block
So how do i have it so that i only have two blocks inside the .item{}?
It seems overkill to me, but you can use a hacky way to do that using a mixin and various functions. Please note that this will work for your specific example but probably not for something else.
I used the helper functions str-to-list and nth-delete, which are not native to SASS.
#mixin parentWithClass($class) {
$parent: nth-delete(str-to-list(#{&}), -1);
#at-root #{selector.replace(&, $parent, #{$parent}#{$class})} {
#content;
}
}
.item {
.inner {
color: blue;
#include parentWithClass(".open") {
color: orange;
}
}
.inner-info {
color: red;
#include parentWithClass(".open") {
color: grey;
}
}
}
You can also nest -info in inner.

How to use this Sass Flexbox mixin provided by a theme

I am using Drupal FortyTwo theme. In the FortyTwo base-theme there is a flexbox mixin provided see below:
#mixin flex-order($number) {
order: #{$number};
}
#mixin flex-align($align) {
#if $align == 'start' or $align == 'end' {
align-items: flex-#{$align};
} #else {
align-items: #{$align};
}
}
#mixin flex-flow($direction: none, $wrap: none) {
#if $wrap != none {
flex-wrap: #{$wrap};
}
#if $direction != none {
flex-direction: #{$direction};
}
}
#mixin flex-grow($value) {
flex-grow: #{$value};
}
#mixin flex-shrink($value) {
flex-shrink: #{$value};
}
#mixin flex-child($value) {
flex: #{$value};
}
#mixin flex($wrap: none, $justify: none, $align: none, $flow: none, $direction: none, $inline: none) {
#if $inline != none {
display: inline-flex;
} #else {
display: flex;
}
#if $direction != none {
flex-direction: #{$direction};
}
#if $wrap != none {
flex-wrap: #{$wrap};
}
#if $align != none {
align-items: #{$align};
}
#if $justify != none {
justify-content: #{$justify};
}
}
I am updating the theme. I can't figure out how to use this mixin? In the old theme there is e.g. this part:
#my-block {
html.flexbox & {
#include flex;
#include bvp(flex-direction, column);
}
div.content {
html.flexbox & {
#include bvp(flex, 1);
}
position: relative;
}
}
Also I have to get rid of the bvp mixin. How do I add flexbox here the proper way using above flexbox mixins?
So as you saw, we have a series of mixins.
The last one should be be most helpful, but from playing around with it in Code Pen, I'm not convinced it actually works correctly. And some of the others aren't especially helpful.
For example, we can see that #mixin flex-order simply spits out the order flexbox property with whatever number we pass to it.
So this:
#my-box {
#include flex-order(2);
}
Outputs this:
#my-box {
order: 2;
}
Well unless you just want a visual reminder that order only relates to flex items, that's not exactly helping you much as you could have just as easily done order: 2 in your SCSS in the first place.
The same thing applies to the mixins flex-align, flex-grow, flex-shrink, and flex-child.
So being that the single-property mixins aren't super useful and the last mixin seems broken, I would recommend just specifying your flex properties as needed in your SCSS and maybe using the flex-flow mixin if you want.
#mixin flex-flow
The flex-flow flexbox property requires two values: one for flex wrapping, and one for flex direction. In the mixin, it outputs that shorthand property as two separate properties, or it outputs only the property you pass to it if you only pass one property, that way you don't end up with an invalid CSS rule.
So this:
#my-box {
#include flex-flow(wrap, column);
}
#my-other-box {
#include flex-flow(wrap);
}
Outputs this:
#my-box {
flex-wrap: wrap;
flex-direction: column;
}
#my-other-box {
flex-wrap: wrap;
}
That way you have two acceptable CSS rules. Otherwise if you actually used the flex-flow property, you'd get:
#my-box {
flex-flow: wrap column; /* invalid; flex-direction must come first */
}
#my-other-box {
flex-flow: wrap; /* invalid; missing flex-direction */
}
Final example
Your final SCSS could look something like this, after removing the bvp mixin and specifying the individual flex properties without mixins, as I initially recommended.
#my-block {
html.flexbox & {
#include flex-flow(row, wrap);
align-items: center;
justify-content: center;
}
div.content {
html.flexbox & {
flex: 1 0 auto;
}
position: relative;
}
}

SCSS How to change order of rendering included mixins

This is a hard question, so I am aware that no one may come up with solution, but that's the problem I really need to solve in my framework.
I have a screen() mixin written in SCSS, which takes $size as an argument, to return any #content wrapped in a media query.
The problem occurs when one element #includes multiple screen() mixins, because resulting media queries will overwrite each other in the same order as they were included. How can I make sure the resulting media queries will be rendered in the correct order (biggest screen to smallest), even if I forget to include them in the right order?
http://sassmeister.com/gist/951520fa83d1e1c69c9d
#mixin screen(
$size: null
){
#if $size == md {
#media (max-width: 1024px) {
#content;
}
}
#if $size == sm {
#media (max-width: 768px) {
#content;
}
}
#if $size == xs {
#media (max-width: 320px) {
#content;
}
}
}
/* output should be 1024, 768, 320 */
.screen {
&:before {
// this should be included as the Last one
#include screen(xs){
content: "xs";
}
#include screen(sm){
content: "sm";
}
// this should be included as the First one
#include screen(md){
content: "md";
}
}
}
I tried to solve that issue by creating placeholder selectors in the right order %media-sm{...}, %media-xs {...}..., and #extend them from the mixin, but #content can't be passed through the #extend directive.
Another solution is a hard one - create an array of keys - sizes, and values - #contents and render them from another function.
No. Sass only does exactly what you tell it to do. If you want your styles to appear in a specific order, write them in that specific order.
Might be easier to pass in the media width you are trying to target:
#mixin media($width) {
#media only screen and (max-width: $width) {
#content;
}
}
#include media(320px) {
background: red;
}

Passing arguments from a mixin to a content block

This open issue in the Sass queue seems to imply passing arguments to #content is not a feature yet, but Susy 2 seems to be able to do this. Tracking down how it's done is a bit of a rabbit hole though and I haven't figured it out yet. Perhaps someone can shed some light with a straightforward example? I want to create a custom mixin that will inherit a layout passed from susy-breakpoint() using a custom map.
Example: Defining a 4 column layout in a global Sass map, will return a width of 100% when a span of 4 is specified inside susy-breakpoint()'s #content. When a custom layout of 8 cols is passed to directly tosusy-breakpoint() via the $layout argument, the nested span() mixin picks up the new layout. But a custom nested mixin will not pick up the new layout. Why?
#import 'susy';
$susy: (
columns: 4,
);
#mixin inherit-layout($layout: 4) {
columns: $layout;
}
#include susy-breakpoint(30em) {
// nested code uses an 4-column grid from global map
.global-cols {
#include span(4);
#include inherit-layout();
}
}
#include susy-breakpoint(48em, $layout: 8) {
// nested code uses an 8-column grid from $layout
.inherited-cols {
#include span(4);
#include inherit-layout();
}
}
Compiled CSS:
#media (min-width: 30em) {
.global-cols {
width: 100%;
float: left;
margin-left: 0;
margin-right: 0;
columns: 4;
}
}
#media (min-width: 48em) {
.inherited-cols {
width: 48.71795%;
float: left;
margin-right: 2.5641%;
columns: 4;
}
}
Update:
I've discovered that making the default variable for the inherit-value() mixin the value of columns key on the existing $susy map allows the mixin to grab context. But why? And why doesn't it work with a different map or outside of susy-breakpoint()?
See here: http://sassmeister.com/gist/d86e217aca3aa8337b83
Susy doesn't pass any arguments to the #content — instead, we change the global variable at the start of the content block, and then change it back at the end:
$example: 4;
#mixin local($local) {
$old: $example;
$example: $local !global;
#content
$example: $old !global;
}
// out here, $example == 4
#include local(12) {
// in here, $example == 12
}

Hide blocks in Susy

Looking at the susy site, how does it hide .secondary when getting at a breakpoint?
Taken from the GutHub source for the site (with other styles removed):
.guides, .tutorial {
.secondary { display: none; } // secondary starts hidden
#include at-breakpoint($break) {
.secondary { display: block; } // secondary becomes visible at breakpoint
}
}
try this:
#include at-breakpoint($break) {
.secondary { display: none; }
}

Resources