How to use this Sass Flexbox mixin provided by a theme - sass

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;
}
}

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.

Sass manipulate with #content

Is it possible to manipulate with #content magic variable in SASS?
I would like to replace some stuff in here before output.
Or maybe can I fill some variable with it?
The conclusion is that, I want to make an mixin #important that create both versions. Important, and no-important.
Input
.test {
#include important {
color: red;
text-align: left;
}
}
Expected output
.test {
color: red;
text-align: left;
}
.test-i {
color: red !important;
text-align: left !important;
}
No, you can't. But I quickly wrote you a mixin to make it work. It doesn't accepts multiple properties (yet).
First Note: I changed the mixin it now does accept multiple properties. Here is the Codepen.
Second Note: I updated the mixin adding multiple properties does no longer compile to different classes for each property, instead you get two versions, one without the !important suffix and one with.
This is the mixin:
#function return($state) {
#return if($state == '', '', '-i');
}
#mixin loop($name, $items...) {
#each $item in $items / 2 {
#each $state in ('', '!important') {
$suffix: return($state);
.#{$name}#{$suffix} {
#for $i from 1 through (length($items) / 2) {
#{nth($items, ($i * 2) - 1)}: #{nth($items, ($i * 2))} #{$state};
}
}
}
}
}
This is how you include it:
// #include loop([classname], [property], [value]);
#include loop(whateverClassname, color, red);
This is what it compiles to:
.whateverClassname {
color: red ;
}
.whateverClassname-i {
color: red !important;
}
This is what it now compiles to, when you use multiple properties at once:
#include loop(whateverClassname, color, red, background-color, green, display, flex);
.whateverClassname {
color: red ;
background-color: green ;
display: flex ;
}
.whateverClassname-i {
color: red !important;
background-color: green !important;
display: flex !important;
}
Conclusion: it works as expected and does no longer bloat your CSS.
Hope I could help you at least a little ;-)

SASS select class that was chained to parent

I have the following HTML <div class="parent green"></div>
The green class may or may not be added. It is dynamic. It may also be another name.
In SASS how do I give properties to a .child element of parent when class green is chained to it?
I tried:
.parent {
.child {
.green & {
color: green;
}
}
}
It doesn't work.
I also tried the following which works but I am looking for something similar to the sass above. The code will become repeatable below because I have to add child each time for every dynamic class.
.parent {
&.green {
.child {
color: green;
}
}
}
I'm trying to get a structure like this if possible with sass:
.parent {
.child {
.green & { /* when .parent.green */
color: green;
}
.blue & { /* when .parent.blue */
color: blue;
}
.text-align-right & { /* when .parent.text-align-right */
text-align: right;
}
etc...
}
}
& is treated as parent selector reference in Sass, because of this your code doesn't work since it refers wrong selector.
Use of & directly will not help here, but your goal can be achieved by using mixins, for example:
#mixin child($class) {
&.#{$class} {
.child {
#content;
}
}
}
.parent {
#include child(green) {
color: green;
}
#include child(blue) {
color: blue;
}
#include child(text-align-right) {
text-align: right;
}
}
This piece of code produces result that you want to get, you can check in by yourself on sassmeister.

Avoid repeat the same mixin in Sass

I have this Mixin for padding utility:
Sass code:
$padding: (
top: "top",
right: "right",
bottom: "bottom",
left: "left",
all: "all"
);
#mixin no-padding($map) {
#each $padding-side, $side in $map {
#if $side == 'all' {
& {
padding: 0 !important;
}
} #else {
&-#{$side} {
padding-#{$side}: 0 !important;
}
}
}
}
Use of it:
.u-noPadding {
#include no-padding($padding);
}
I want to use the same Mixin but now for margin, is there any solution to avoid repeating the same mixin and make a good use of best practices?
#mixin no($type,$sides:null) {
$i:0 !important;
#if $sides == null {
#{$type}:$i;
} #else {
#each $side in $sides {
#{$type}-#{$side}:$i;
}
}
}
.u-noPadding {
#include no(padding, top left etc...); // choose any side separated with a space
}
.u-noMargin {
#include no(margin); // instead of 'all', type nothing
}
Like this? Your $sides will be stored in a temporary map automatically if your second parameter is set, no need extra map for this.
About the second parameter: If you want no sides, let it empty and all sides will have 0. Similiar to your 'all' idea.. it's shorter.

SASS: create name that is unique per-mixin?

I'm creating a mixin called static() that is used inside another mixin to separate the static properties out into placeholders, so that those properties aren't repeated in the output every time a mixin is used. Here's how you would use it in a mixin called button(), for example:
#mixin button($color) {
#include static('button') {
border: 1px solid;
border-radius: 5px;
padding: .25em .5em;
&:hover {
cursor: pointer;
}
}
background-color: $color;
&:hover {
background-color: mix(black, $color, 15%;
}
}
Here's the code for the static() mixin:
#mixin static($mixin-name, $extend: true) {
// set global $Placeholder-Selectors if it doesn't already exist
$Placeholder-Selectors: () !global !default;
$selector: map-get($Placeholder-Selectors, $mixin-name);
#if $extend == true {
#if $selector == null {
$selector: unique-id();
$Placeholder-Selectors: map-merge($Placeholder-Selectors, ($mixin-name: $selector)) !global;
#at-root %#{$selector} {
#include static($mixin-name, false) {
#content;
};
}
}
#extend %#{$selector};
} #else {
#content;
}
}
The only purpose of the variable $mixin-name is to make sure the declarations of the created placeholder are not overwritten by another placeholder of the same name. My assumption is that the best way to ensure this is to use the name of the mixin itself for the $Placeholder-Selectors' key (since this will be unique to the mixin).
Question:
If that assumption is correct, I don't want to have to type out the name of the mixin I'm using (as in "#include static('button')")...so, in the static() mixin, is there a way to dynamically determine the name of the mixin that static() is being used inside?
Or, is there another way to ensure a placeholder that is unique per-mixin?
No. Sass does not have a way to get any of the names of the mixins used.
That said, you're over-engineering. All you need to do is setup your extend selector outside of the mixin.
%common-button-styles {
border: 1px solid;
border-radius: 5px;
padding: .25em .5em;
&:hover {
cursor: pointer;
}
}
#mixin button($color) {
color: $color;
#extend %common-button-styles;
&:hover {
background-color: mix(black, $color, 15%);
}
}
If you're jumping through all of these hoops in an attempt to avoid creating duplicate extend only selectors via multiple imports, what you're looking for is called import once. If you're a Compass user, 1.0 includes an extension by default that does this. If not, a quick search will show you a few different ways of implementing such a feature.

Resources