Css Preprocessor Mixins Notes
Css Preprocessor Mixins Notes
Some things in CSS are a bit tedious to the @mixin directive and give it a
write, especially with CSS3 and the many name. We've named our mixin theme.
vendor prefixes that exist. A mixin lets We're also using the
you make groups of CSS declarations variable $theme inside the parentheses so
that you want to reuse throughout your we can pass in a theme of whatever
site. It helps keep your Sass we want. After you create your mixin,
very DRY. You can even pass in values to you can then use it as a CSS declaration
make your mixin more flexible. Here's an starting with @include followed by the
example for theme. name of the mixin.
SCSS
Sass Extend/Inheritance
CSS Using @extend lets you share a set
SCSS SYNTAX of CSS properties from one selector to
@mixin theme($theme: DarkGray) {
background: $theme; another. In our example we're going to
box-shadow: 0 0 1px rgba($theme, .25);
color: #fff;
create a simple series of messaging for
} errors, warnings and successes using
.info { another feature which goes hand in
@include theme; hand with extend, placeholder classes. A
}
.alert { placeholder class is a special type of
@include theme($theme: DarkRed); class that only prints when it is extended,
}
.success { and can help keep your
}
@include theme($theme: DarkGreen);
compiled CSS neat and clean.
SCSS
Sass
CSS
CSS OUTPUT
.info { SCSS SYNTAX
background: DarkGray; /* This CSS will print because %message-
box-shadow: 0 0 1px rgba(169, 169, shared is extended. */
169, 0.25); %message-shared {
color: #fff; border: 1px solid #ccc;
} padding: 10px;
color: #333;
.alert { }
background: DarkRed;
box-shadow: 0 0 1px rgba(139, 0, 0, // This CSS won't print because %equal-
0.25); heights is never extended.
color: #fff; %equal-heights {
} display: flex;
flex-wrap: wrap;
.success { }
background: DarkGreen;
box-shadow: 0 0 1px rgba(0, 100, 0, .message {
0.25); @extend %message-shared;
color: #fff; }
}
.success {
@extend %message-shared; @use "sass:math";
border-color: green;
} .container {
display: flex;
.error { }
@extend %message-shared;
border-color: red; article[role="main"] {
} width: math.div(600px, 960px) * 100%;
}
.warning {
@extend %message-shared; aside[role="complementary"] {
border-color: yellow; width: math.div(300px, 960px) * 100%;
} margin-left: auto;
}
What the above code does is
CSS OUTPUT
tells .message, .success, .error, and .warni .container {
ng to behave just like %message-shared. display: flex;
}
That means anywhere that %message-
shared shows article[role="main"] {
width: 62.5%;
up, .message, .success, .error, & .warning }
will too. The magic happens in the aside[role="complementary"] {
generated CSS , where each of these width: 31.25%;
margin-left: auto;
classes will get the same CSS properties }
as %message-shared. This helps you avoid
having to write multiple class names
We've created a very simple fluid grid,
on HTML elements.
based on 960px. Operations in Sass let
You can extend most
us do something like take pixel values
simple CSS selectors in addition
and convert them to percentages
to placeholder classes in Sass, but using
without much hassle.
placeholders is the easiest way to
make sure you aren't extending a class
that's nested elsewhere in your
styles, which can result in unintended
selectors in your CSS. Variables
Note that the CSS in %equal-heights isn't
$red: #833;
generated, because %equal-heights is body {
never extended. color: $red;
}
Operators Nesting
Doing math in your CSS is very helpful. .markdown-body {
Sass has a handful of standard math a{
operators like +, -, *, math.div(), and %. In color: blue;
&:hover {
our example we're going to do some
color: red;
simple math to calculate widths for }
an article and aside. }
SCSS }
Sass to properties
text: {
CSS align: center; // like text-align: center
SCSS SYNTAX
transform: uppercase; // like text-transform: Instead, we should use the @use rule.
uppercase The .scss or .sass extension is optional.
} #Color functions
Comments
rgba
/* Block comments */
// Line comments rgb(100, 120, 140)
rgba(100, 120, 140, .5)
Mixins rgba($color, .5)
@mixin heading-font { Mixing
font-family: sans-serif;
font-weight: bold; mix($a, $b, 10%) // 10% a, 90% b
} Modifying HSLA
h1 {
@include heading-font; darken($color, 5%)
} lighten($color, 5%)
with parameters saturate($color, 5%)
@mixin font-size($n) { desaturate($color, 5%)
font-size: $n * 1.2em; grayscale($color)
} adjust-hue($color, 15deg)
body { complement($color) // like adjust-hue(_, 180deg)
@include font-size(2); invert($color)
} fade-in($color, .5) // aka opacify()
with default values fade-out($color, .5) // aka transparentize() - halves
@mixin pad($n: 10px) { the opacity
padding: $n; rgba($color, .5) // sets alpha to .5
}
Getting individual values
body {
@include pad(15px); HSLA
} hue($color) // → 0deg..360deg
with a default variable saturation($color) // → 0%..100%
// Set a default value lightness($color) // → 0%..100%
$default-padding: 10px; alpha($color) // → 0..1 (aka opacity())
@mixin pad($n: $default-padding) { RGB
padding: $n; red($color) // → 0..255
} green($color)
body { blue($color)
@include pad(15px); See: hue(), red()
}
Adjustments
Extend
// Changes by fixed amounts
.button { adjust-color($color, $blue: 5)
··· adjust-color($color, $lightness: -30%) // like
} darken(_, 30%)
.push-button { adjust-color($color, $alpha: -0.4) // like fade-
@extend .button; out(_, .4)
} adjust-color($color, $hue: 30deg) // like adjust-
Composing hue(_, 15deg)
// Changes via percentage
@import './other_sass_file'; scale-color($color, $lightness: 50%)
@use './other_sass_file'; // Changes one property completely
The @import rule is discouraged because will get change-color($color, $hue: 180deg)
eventually removed from the language. change-color($color, $blue: 250)
Supported: $red $green $blue $hue $saturation $ligh feature-exists(global-variable-shadowing)
tness $alpha Features
#Other functions
global-variable-shadowing
extend-selector-pseudoclass
units-level-3
at-error
Strings
For loops
unquote('hello')
@for $i from 1 through 4 {
quote(hello)
.item-#{$i} { left: 20px * $i; }
to-upper-case(hello)
}
to-lower-case(hello)
str-length(hello world) Each loops (simple)
str-slice(hello, 2, 5) // "ello" - it's 1-based, not 0-
based $menu-items: home about services contact;
str-insert("abcd", "X", 1) // "Xabcd"
@each $item in $menu-items {
Units .photo-#{$item} {
background: url('images/#{$item}.jpg');
unit(3em) // 'em'
}
unitless(100px) // false
}
Numbers
Each loops (nested)
floor(3.5)
$backgrounds: (home, 'home.jpg'), (about,
ceil(3.5)
'about.jpg');
round(3.5)
abs(3.5)
@each $id, $image in $backgrounds {
min(1, 2, 3)
.photo-#{$id} {
max(1, 2, 3)
background: url($image);
percentage(.5) // 50%
}
random(3) // 0..3
}
Misc
While loops
variable-exists(red) // checks for $red
$i: 6;
mixin-exists(red-text) // checks for @mixin red-text
@while $i > 0 {
function-exists(redify)
.item-#{$i} { width: 2em * $i; }
global-variable-exists(red)
$i: $i - 2;
selector-append('.menu', 'li', 'a') // .menu li a
}
selector-nest('.menu', '&:hover li') // .menu:hover li
selector-extend(...)
selector-parse(...)
selector-replace(...)
selector-unify(...)
Conditionals
@media #{$tablet}
font: #{$size}/#{$line-height}
url("#{$background}.jpg")
Lists
$list: (a b c);
map-get($map, key1)