-
-
Save sarahdayan/4d2cc04a636e8039f10a889a0e29fbd9 to your computer and use it in GitHub Desktop.
// ---- | |
// Sass (v3.4.21) | |
// Compass (v1.0.3) | |
// ---- | |
// Sass modifiers mixin by Sarah Dayan | |
// Generate All Your Utility Classes with Sass Maps: frontstuff.io/generate-all-your-utility-classes-with-sass-maps | |
// http://frontstuff.io | |
// https://github.com/sarahdayan | |
$colors: ( | |
red: #ff3538, | |
grey: ( | |
base: #404145, | |
light: #c7c7cd | |
), | |
yellow: ( | |
base: #ecaf2d | |
), | |
green: ( | |
base: #5ad864 | |
) | |
); | |
$font-sizes: ( | |
small: 12px, | |
medium: 14px, | |
large: 16px, | |
x-large: 18px, | |
xx-large: 20px | |
); | |
@mixin modifiers($map, $attribute, $prefix: '-', $separator: '-', $base: 'base') { | |
@each $key, $value in $map { | |
&#{if($key != $base, #{$prefix}#{$key}, '')} { | |
@if type-of($value) == 'map' { | |
@include modifiers($value, $attribute, $separator); | |
} | |
@else { | |
#{$attribute}: $value; | |
} | |
} | |
} | |
} | |
.text { | |
@include modifiers($colors, 'color', $separator: ':'); | |
@include modifiers($font-sizes, 'font-size', '--'); | |
} |
.text-red { | |
color: #ff3538; | |
} | |
.text-grey { | |
color: #404145; | |
} | |
.text-grey:light { | |
color: #c7c7cd; | |
} | |
.text-yellow { | |
color: #ecaf2d; | |
} | |
.text-green { | |
color: #5ad864; | |
} | |
.text--small { | |
font-size: 12px; | |
} | |
.text--medium { | |
font-size: 14px; | |
} | |
.text--large { | |
font-size: 16px; | |
} | |
.text--x-large { | |
font-size: 18px; | |
} | |
.text--xx-large { | |
font-size: 20px; | |
} |
This is great, Sarah. Do you have any ideas for how to modify this to support passing multiple attributes to the mixin? For instance, I'm iterating through our spacing scale and creating .padding-x-<size>
classes that would include both padding-left
and padding-right
attributes.
Edit: I figured it out. Basically adding another check to see if $attribute
is a list and looping through them. See here: https://gist.github.com/mattfelten/5c6ad6edb70c6ab10f5c377c21eda2f2
Why isn't separator
used in the modifiers mixin?
@sarahdayan, this is awesome. Could you please explain how negative values (eg. -4px) can be supported? Is there a way to handle @media queries in the @mixin for handy breakpoint changes?
@sarahdayan Amazing gist, I've built something nice with it.
@raphaelobene check how I'm using this to generate negative margin. For media I think you can use some condition as I'm doing here in the case of default. Also you can try wrapping the the class with media queries and passing different sizes but I'm not sure if it will generate the css you want but you can try it.
/** Custom CSS Variables **/
:root {
--ion-space-xs: 4px;
--ion-space-sm: calc(var(--ion-space-xs) * 2);
--ion-space-md: calc(var(--ion-space-xs) * 3);
--ion-space: calc(var(--ion-space-xs) * 4);
--ion-negative-space-xs: calc(var(--ion-space-xs) * -1);
--ion-negative-space-sm: calc(var(--ion-space-md) * -1);
--ion-negative-space-md: calc(var(--ion-space-md) * -1);
--ion-negative-space: calc(var(--ion-space) * -1);
}
$spaces: (
xs: var(--ion-space-xs),
sm: var(--ion-space-sm),
md: var(--ion-space-md)
);
$negative-spaces: (
xs: var(--ion-negative-space-xs),
sm: var(--ion-negative-space-sm),
md: var(--ion-negative-space-md),
default: var(--ion-negative-space)
);
@mixin class-variations($args, $attribute: 'padding', $prefix: '') {
@each $key, $value in $args {
@if $key == 'default' {
&#{$prefix} {
#{$attribute}: $value;
}
} @else {
&#{$prefix}-#{$key} {
#{$attribute}: $value;
}
}
}
}
// Generate padding variations
.ion-padding {
@include class-variations($args: $spaces);
@include class-variations($args: $spaces, $attribute: 'padding-top', $prefix: '-top');
@include class-variations($args: $spaces, $attribute: 'padding-left', $prefix: '-start');
@include class-variations($args: $spaces, $attribute: 'padding-right', $prefix: '-end');
@include class-variations($args: $spaces, $attribute: 'padding-bottom', $prefix: '-bottom');
}
// Generate margin variations
.ion-margin {
@include class-variations($args: $spaces);
@include class-variations($args: $spaces, $attribute: 'margin-top', $prefix: '-top');
@include class-variations($args: $spaces, $attribute: 'margin-left', $prefix: '-start');
@include class-variations($args: $spaces, $attribute: 'margin-right', $prefix: '-end');
@include class-variations($args: $spaces, $attribute: 'margin-bottom', $prefix: '-bottom');
}
.ion-negative-margin {
@include class-variations($args: $negative-spaces, $attribute: 'margin-top', $prefix: '-top');
@include class-variations($args: $negative-spaces, $attribute: 'margin-left', $prefix: '-start');
@include class-variations($args: $negative-spaces, $attribute: 'margin-right', $prefix: '-end');
@include class-variations($args: $negative-spaces, $attribute: 'margin-bottom', $prefix: '-bottom');
}
Thanks for the article, very well explained!
Thanks for the article and making this gist. Using Sass mixins for utility classes in order to keep things leaner and simpler than say Tachyons or Tailwind is a great idea! Only thing I wondered, as I can't see any easy way to do this, would it be at all possible to also incorporate @media queries in this mixin for handy breakpoint changes to your utilities?