css • SASS.scss preprocessor - martindubenet/wed-dev-design GitHub Wiki
Dart is the new
libSass
Since 2021 LibSASS is deprecated in favor of Dart Sass.
"devDependencies": {
"sass": "^1.50.0"
},
A common practice is to compile SASS and Javascript sources files « ./src
» to a « ./dist
» repository.
Originals | Compiled |
---|---|
/src/sass/ /src/javascript/main.js
|
/dist/css/ /dist/js/main.js
|
Set npm «./package.json» to compile from/to the two common repositories.
{
"name": "theme",
"version": "1.0.1",
"description": "PROJECT_DESCRIPTION",
"author": "PROJECT_AUTHOR",
"license": "ISC",
"main": "assets/js/main.js",
"devDependencies": {
"sass": "^1.50.0"
},
"scripts": {
"watch": "sass src/sass:assets/css --embed-sources --style=compressed --quiet --watch",
"compile": "sass src/sass:assets/css --embed-sources --style=compressed"
}
}
https://sass-lang.com/documentation/cli/migrator
npm install -g sass-migrator
- assign the migration name to a specific file:
sass-migrator module style.scss
.
@use '_variables.scss';
@use 'buttons' as *; // the star removes any namespace
@use 'forms' as f;
a{ color: variables.$primary; }
$btn-color: $color; // buttons.$color without a namespace
$form-border: f.$input-border; // forms.$input-border with a custom namespace
The @at-root
causes everything within it to be interpolated at the root of the document instead of using the normal nesting.
We can NOT nest multiple level of
@at-root
.
/* scss */
.selector {
@at-root .parent #{&} { … }
@at-root .sibling#{&} { … }
@at-root #{&} .child { … }
}
/* compiled css */
.parent .selector { … }
.selector.sibling { … }
.selector .child { … }
Sass will gradually phase out
@import
over the next few years, and eventually remove it from the language entirely. Prefer the@use
rule instead.
The @import
rule extends the CSS at-rule
to load styles, mixins, functions, and variables from other stylesheets. Unlike plain CSS imports, which require the browser to make multiple HTTP requests as it renders your page, Sass imports are handled entirely during compilation.
These two rules are confusing because they kind of do the same task but
The rule is written @forward "". It loads the module at the given URL just like @use, but it makes the public members of the loaded module available to users of your module as though they were defined directly in your module. Those members aren’t available in your module, though—if you want that, you’ll need to write a @use rule as well. Don’t worry, it’ll only load the module once!
If you do write both a @forward and a @use for the same module in the same file, it’s always a good idea to write the @forward first. That way, if your users want to configure the forwarded module, that configuration will be applied to the @forward before your @use loads it without any configuration.
A stylesheet’s
@use
rules must come before any rules other than@forward
, including style rules. However, you can declare variables before@use
rules to use when configuring modules.
The @use
rule loads mixins, functions, and variables from other Sass stylesheets, and combines CSS from multiple stylesheets together.
Using @forward
rule loads a Sass stylesheet and makes its mixins, functions, and variables available when your stylesheet is loaded with the @use
rule. It makes it possible to organize Sass libraries across many files, while allowing their users to load a single entrypoint file.
Since Dart compiler is the standard #{$}
interpolation is required for parsing Sass variables as CSS var()
.
Read this post about «CSS4 Variables with Fallbacks Using Sass» from Jake Albaugh to understand how to interpolate Sass variables within :@root{}
CSS variables.
// Sass variable
$sass_var: #FEFEFE;
// Sass map
$array-name: (
"array-key0": #FEFEFE,
"array-key1": #EEE,
"array-key2": #FFF,
);
/**
* From Sass to CSS ↴
*/
// CSS variables
:root {
@each $arrayKey, $arrayValue in $array-name {
--cssVar-#{$arrayKey}: #{$arrayValue};
}
--cssVar: map-get($array-name, "array-key0");
--cssVar: #{$sass_var};
--cssVar: #FEFEFE;
}
// CSS Style
.selector{
.color: var(--varCss);
}
Mixin names, like all Sass identifiers, treat hyphens and underscores as identical. This means that reset-list and reset_list both refer to the same mixin. This is a historical holdover from the very early days of Sass, when it only allowed underscores in identifier names. Once Sass added support for hyphens to match CSS’s syntax, the two were made equivalent to make migration easier.
- Declare a mixin :
@mixin mixinExample(…){…}
- Use that mixin within SCSS :
@include mixinExample
Learn more about using #{$arguments}
as an array or how to use @content
blocks as a slot from the official documentation. All this to ad flexibility to your mixins.
Adding !default
at the end of a Sass variable means that this variable is likely to be redefined later in the cascade of the imported files, in which case the other declared variable will be prioritized regardless of its position in the reading cascade logic.
Using this declaration is highly recommended as it is a counter part of using the !important
declaration which generates many nightmares at maintenance and is bad for CSS reading performance.
- Online sass color generator : http://scg.ar-ch.org/
- New since Dart Sass : https://sass-lang.com/documentation/modules/color
- « Using a Sass map for my colors » by Kevin Powell youtuber
Converts hex color value to RGB.
RGB values
no more requires to be seperated by comas*,*,*
@function toRgb($hexColor) {
@return "rgb("+ red($hexColor) +" "+ green($hexColor) +" "+ blue($hexColor) +")";
}
// Applyed
$rgbColor: hexToRgb(#2d3c54);
@debug "rgbColor": #{$rgbColor};
Listing color
parameters:
-
color.red()
: RGB, -
color.green()
: RGB, -
color.blue()
: RGB, -
color.alpha()
: HSL, -
color.hue()
: HWB, -
color.lightness()
: HSL, -
color.opacity()
: transparency, -
color.saturation()
: HSL, -
color.whiteness()
: HWB, -
color.blackness()
: HWB,
Parameter usage:
-
color.adjust($parameter: $amount)
allows us to increases or decreases one or more properties of$color
by fixed amounts, -
color.adjust($color, $hue: $degrees)
now replace the previous,adjust-hue($color, $degrees)
-
color.alpha($color, $opacity)
orcolor.opacity($color, $alpha)
, -
color.blackness($color)
, -
color.$parameter($color)
gives us the value of the parameter used in that($color)
,
function | example | new math module |
---|---|---|
Ceil |
ceil(1.25) = 2 |
math.ceil() |
Floor |
floor(1.75) = 1 |
math.floor() |
Percentage |
percentage( $value100 / $value50 ) = 200% = percentage( 2.0 )
|
math.percentage() |
Random |
random(100) = 0>99 |
math.random() |
function | example | new string module |
---|---|---|
Lenght | lenght($example) |
string.length($example) |
To lower case | to-lower-case($example) |
string.to-lower-case($example) |
Unique ID | unique-id() |
string.unique-id() |
@import "~bootstrap";
Prepending module paths with a ~
tells webpack and/or npm loader to search through node_modules. It's important to prepend it with only ~
, because if you add a slash after the tilde character (~/
) it indicates your personal to the home directory and we don't want that.
How to code CSS using BEM nomenclature on SASS preprocessor stylesheets. Here is a real world tutorial from CSS-Tricks.
<p class="main-style">Main style example</p>
<p class="main-style--variant-style">Variant style example</p>
<div class="main-style">
<p class="main-style__child-style">Child within main style example</p>
</div>
.main-style {
color: gray;
//
&--variant-style {
color: orange;
}
&__child-style {
color: blue;
}
}
#{
$…}
To parse a quoted string
$img-path-to-assets: '../img';
background-image: url(#{$img-path-to-assets}/logo.png)
This rule causes everything within it to be interpolated at the root of the document instead of using the normal nesting. We can NOT nest multiple an `@at-rule Reference
SCSS vs CSS
.selector { .selector {
background: gray; background: gray;
// }
@at-root .parent #{&} { .selector .thisClass {
background: blue; background: blue;
} }
@at-root .sibling#{&} { .sibling.selector {
background: green; background: green;
} }
@at-root #{&} .child { .selector .child {
background: red; background: red;
} }
}
This loop is to assign any color from Bootstrap Theme to a custom call
@each $themeColor, $value in $theme-colors {
.link-hover--#{$themeColor} {
@include hover-focus(){
color: $value !important;
}
}
}
This is useful to replicate a common macro style accros many contexts without duplicating it everytime. Simply declare it once ABOVE then paste that style where you need it later in the cascade.
Useful for extending Bootstrap class (ex.:
.sr-only
) within your own projet stylesheets.
.common-style {
font-weight: bold;
color: white;
}
.example {
@extend .common-style !optional;
}
Choose your easing function from easings.net
@mixin anim_transition($duration:0.3, $cssProperty:all, $easingFunction:ease) {
$duration_s: $duration + s; //string interpolation as seconds
//
transition: $cssProperty $duration_s $easingFunction;
}
@mixin anim_opacity( $duration:1, $keyFrameName:blink, $animStyle:infinite ) {
$duration_s: $duration + s;
//
@keyframes #{$keyFrameName} {
0% { opacity: 1; }
100% { opacity: 0; }
}
animation: $keyFrameName $duration_s $animStyle;
}
@mixin anim_rotate90($speed:1, $keyFrameName:spin, $animStyle:infinite) {
$speed_s: $speed + s;
//
@keyframes #{$keyFrameName} {
0% { transform: rotate(0deg); }
100% { transform: rotate(90deg); }
}
animation: $keyFrameName $speed_s $animStyle;
}
@mixin bg_size ($value: 100%) {
-webkit-background-size: $value;
-moz-background-size: $value;
-o-background-size: $value;
background-size: $value;
}
@mixin background_pattern_image(
$stroke1color: transparent,
$stroke2color: rgba(255, 255, 255, 0.25),
$stroke1width: 20px,
$stroke2width: 20px,
$patternAngle: 315deg
) {
background-image: repeating-linear-gradient(
$patternAngle,
$stroke1color 0,
$stroke1color $stroke2width,
$stroke2color $stroke2width,
$stroke2color ($stroke1width + $stroke2width)
);
}
@mixin chevron_shape ($size, $borderWidth:1px, $rotation:-45deg, $padding: floor($size /2)) {
display: inline-block;
width: $size;
height: $size;
padding: $padding;
border: solid blue;
border-width: 0 $borderWidth $borderWidth 0;
transform: rotate($rotation);
}
/*
* Useful for creating pointing arrows to a direction
* <i.icon__pointing-arrow--to-right>,
* <i.icon__pointing-arrow--to-left>
*/
.icon {
&__pointing-arrow {
&--to-right {
@include chevron_shape(5px, 2px);
margin-left: 0.75rem;
}
&--to-left {
@include chevron_shape(5px, 2px, 135deg);
margin-right: 0.75rem;
}
}
}
@mixin dimensions ($width: 1px, $height: 1px ) {
width: $width;
height: $height;
}
Original post : « SASS function loop for headings h1, h2, h3, h4, h5, h6 » by Alex
@function headingTags ($from: 1, $to: 6) {
@if $from == $to {
@return 'h#{$from}';
}
@else {
@return 'h#{$from},' + headingTags($from+1, $to);
}
}
Usage
#{headings(1,6)} {
color: white;
}
Clean fallback (not a hack) for IE (previous to Edge) browsers
Kendo script adds a class to identify the browsers on the html tag : <html class="k-ie k-ie11">
. This mixins rely on that browser detection script.
@mixin cssVar_ie_fallback($css_property, $default_value, $ie_value: $default_value) {
#{$css_property}: $default_value;
html.k-ie & {
#{$css_property}: $ie_value;
}
}
/**
* Responsive media queries
* `@include responsive_media(min-width, 1200px, false)`
*/
@mixin responsive_media( $attr: min-width, $breakpoint: 320px, $mediaPrint: false ) {
@if $mediaPrint {
@media print and ($attr: $breakpoint) {
@content;
}
} @else {
@media screen and ($attr: $breakpoint) {
@content;
}
}
}
Style input's placeholders to make it look different when not filled. Expending Bootstrap4 $input-color-placeholder
to more browsers.
Author: www.stackoverflow.com/questions/20773665/fail-to-change-placeholder-color-with-bootstrap-3
@mixin placeholder_fontStyleColor ($style: normal, $color: #ccc) {
// Old Safari and Chrome
&::-webkit-input-placeholder {
font-style: $style;
color: $color;
}
// Old Firefox
&::-moz-placeholder {
font-style: $style;
color: $color;
opacity: 1; // Override Firefox's unusual default opacity; See //github.com/twbs/bootstrap/pull/11526
}
// Microsoft IE 10-11
&:-ms-input-placeholder {
font-style: $style;
color: $color;
}
// Microsoft Edge
&::-ms-input-placeholder {
font-style: $style;
color: $color;
}
// w3c
&::placeholder {
font-style: $style;
color: $color;
}
}
- Control aspect ratio to center align child tag. The logic is based on Bootstrap3.
- Default ratio is 16:9 but can be set to whatever required.
- Requirement: Can only contain ONE of either , <iframe>, or tags and nothing else.
@mixin fixedRatio_toChild ( $ratioX: 16, $ratioY: 9, $framePadding: 0 ) {
position: relative;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
padding: 0;
//
&:before {
content: '';
display: block;
padding-top: ($ratioY / $ratioX) * 100%;
}
// child containers
> iframe,
> object,
> video {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
// child images
> img {
flex: 0 0 auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
max-width: 100%;
width: auto;
height: auto;
max-height: 100%;
padding: $framePadding;
}
}
Use Text Shadow as wrapping border around text
@mixin textShadow_asBorder ($borderCorlor: black ) {
text-shadow: -1px -1px 0 $borderCorlor, 1px -1px 0 $borderCorlor, -1px 1px 0 $borderCorlor, 1px 1px 0 $borderCorlor;
}
A bunch of application plugins exist to compile Sass and SCSS files for small personnal tasks but if your are developing an important project with coleagues the standard is to set-up an npm (or yarn) package.json
file from where you will set scripts to either update you CSS files as you save your Sass files or executing simply compiling all before doing your git commit
.
myTheme/dist/css/myTheme.css
myTheme/src/sass/myTheme.scss
myTheme/package.json**
Stylesheet repository | Description |
---|---|
~/dist/css |
The « distributable files » are a production-ready compiled version of your code. |
~/src/sass |
The original development's « source files ». |
Sass Directive | Description |
---|---|
--embed-sources |
Tells Sass to generate the «*.css.map » file that allow traceback to SCSS file's line numbers when Web Inspecting compiled CSS in the Browser. It is a good practice to push these files on Dev/QA/Staging servers but maybe not in Production. |
--quiet |
Tells Sass NOT to emit any warnings. |
--style=compressed |
Tells Sass to minify when exported as static CSS file. |
--watch |
Tells Sass to keep on re-compiling CSS files everytime the OS detects that you save a changed file. |
The four Sass directives above are used in the following package's scripts
lines below to compile any stylesheet files contained within ~/src/sass
to the ~/dist/css
directory.
{
"name": "myTheme",
"version": "1.0.0",
"description": "Front-end stack for custom wordpress theme",
"author": "",
"license": "ISC",
"main": "dist/js/theme.js",
"devDependencies": {
"sass": "^1.42.1"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"watch-sass": "sass src/sass:dist/css --embed-sources --style=compressed --watch",
"compile-sass": "sass src/sass:dist/css --embed-sources --style=compressed --quiet"
}
}