Sass
Improving Front-End Workflow with CSS Preprocessing
Why?
- Extends CSS in a logical way
- Improves maintainability
- Improves scalability
- Promotes modularity
- DRYs out code
What?
- CSS extension language
- SCSS or Sass format compiles into CSS
- Open source and created using Ruby (C implementation exists as well - better performance)
- Vanilla CSS is valid SCSS
How?
- All Sass files located in /sass folder in root
- Compile to /stylesheets
- All Sass partials imported into main.scss
- Imported partials denoted by underscore
@import
"Utilities/_vars.scss",
"Utilities/_mixins.scss",
"Base/_reset.scss";
Where?
- All necessary files can be found on ftp
- \\ftp\Graphics\+ Creative Resources\FED Project Setup
- gulpfile, package.json, build events, and Sass basic structure
Structure - Base
- Animations
- All keyframe animations
- Framework
- Foundation (GRID only)
- Global
- Global classes, generic components, general global styles
- Reset
- Standard browser reset
- Structure
- Navigation, Header, Footer
- Typography
- Font face declarations, global typography styles, rich text (WYSIWYG) styles, typography classes (silent & otherwise)
Structure - Utilities
- _mixins.scss
- Contains all mixin declarations
- _vars.scss
- Contains all variables and maps: media queries, colors, fonts, page/block-specific pixel/percentages
Structure - Other
- Components
- All component-specific styles
- FeatureDetection
- Global browser-specific or global touch-specific styles
- Pages
- All template-specific styles
- Responsive
- Global responsive styles (rarely used) - older projects
Compiling
- Web Workbench (older projects)
- Install Mindscape Workbench; compiles on save automatically (make sure /stylesheets folder is checked out!)
- Issues:
- TFS
- Ruby-based = slow (~15 seconds)
- Often generates unwanted .css files
- Hates life
Compiling
- Gulp (newer projects)
- Run "npm install" in directory with package.json file
- Run "gulp sass:watch" to start watch task
- "gulp sass:build" will compile CSS
- Don't forget to disable Workbench/Web Essentials
- Improvements:
- No TFS issues
- Fast (C based)
- Autoprefixer - no need to worry about vendor prefixes
- Source maps in Dev Tools
Troubleshooting
- Gulp depends on:
- iojs - 32bit
- Git - "Use from Windows Command Prompt"
- Python 2.7.x
- "gulp not recognized command" error
- Install gulp globally ("npm install gulp -g")
- FYI: "stylesheets/main.css" is not included in the project - is created as a hidden file
Deployment
- Should be a pre-build event to automatically compile Sass
- cd $(ProjectDir)
call npm install
call gulp sass:build-prod - "gulp sass:build-prod" should be used for any production deployments
- Autoprefixer, minification
- TFSBuild knows how to gulp!
- Include in automated builds
Getting Started
- Basic syntax is virtually identical to CSS
- Partial structure:
- General styles (some times split up further by section)
- Media queries, in descending order
Getting Started
- Safely modify any Pages/Components sass files
- Generally should not be modifying any Base files
- Add classes to appropriate template-specific or component-specific Sass partial
- Make sure your class name is specific - CSS is global scope!
- ".module-description"
- Never ".button", ".container", etc.
Nesting
- Useful for clear visual hierarchy
- To nest pseudo-classes/elements:
- &:hover, &:before, etc.
- To nest stacked classes:
- &.class-name
- Caveats
- Never nest more than three levels deep - creates overly specific selectors
Nesting Ex.
- Class naming:
- All lowercase separated by hyphens
- Semantically
- .module-description
- Allows for utilization of nesting w/o unnecessarily increasing selector specificity - new in Sass 3.4+
.module {
&-title {
color: red;
&:before {
content: "hi";
}
}
&-desc {
color: blue;
}
}
<div class="module">
<p class="module-title"></p>
<span class="module-desc"></p>
</div>
Nesting Cont.
- Seriously, no more than 3 levels deep
- Selector specificity should never exceed (0, 0, X, Y) where X + Y < 4
- IDs should never be used as selectors
Variables
- Store information that needs to be reused
- Properties:
- Media query breakpoints
- All colors
- Font facts
- Non-arbitrary pixel/percentage values
- If a value is used multiple times, a variable should be created
- Avoid "magic numbers" - use variables to calculate new values to ensure clarity
- To pass a variable into a calc() function, interpolate
Variable Ex.
Declare a variable
$accent-color: #000;
$column-gutter: 30px;
Use a variable
right: ($max-width - $column-gutter);
width: calc(100vh - #{$column-gutter});
Extend
- Share a set of properties
- Important for DRY CSS
- Helps prevent class overload
- Ensures consistency
- Should only ever extend silent classes
- Ensures relationships formed only around the correct properties
Extend Ex.
- Extend typography
%lt-sans-serif {
font-family: $sans-serif-lt-font;
font-size: .9em;
line-height: 1.5em;
}
.paragraph {
@extend %lt-sans-serif;
}
- Extend grouping
%fixed-arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: map-get($zindex, z-index-1);
svg {
fill: #fff;
pointer-events: none;
}
}
.previous-arrow {
@extend %fixed-arrow;
left: 0;
}
.right-arrow {
@extend %fixed-arrow;
right: 0;
}
Mixins
- Group reusable declarations and pass in a value
- Base mixins included in _mixins.scss partial:
- Backwards compatibility
- Transitions
- Hardware acceleration
- Gradients
- Animations
- + more!
@mixin multiline-ellipsis($number) {
display: -webkit-box;
-webkit-line-clamp: $number;
text-overflow: ellipsis;
overflow: hidden;
-webkit-box-orient: vertical;
}
Mixin declaration
.class {
@include multiline-ellipsis(5);
}
Mixin usage
Mixins Cont.
- Can accept multiple values (with option to define default value)
- Can accept @content blocks
@mixin transition($time, $property: all, $easing: ease-in) {
transition: $property $time $easing;
-webkit-transition: $property $time $easing;
-moz-transition: $property $time $easing;
-o-transition: $property $time $easing;
}
@mixin apply-to-ie6-only {
* html {
@content;
}
}
@include apply-to-ie6-only {
#logo {
background-image: url(/logo.gif);
}
}
* html #logo {
background-image: url(/logo.gif);
}
Compiles to:
Maps
- Represent an association between keys and values
- New to 3.4+!
- Should be used for z-index values to prevent insanity
- Useful with @each loops
Maps Ex.
Z-index map
$zindex: (
z-index-0 : -1,
z-index-00 : 0,
z-index-1 : 10,
z-index-2 : 20,
z-index-3 : 30
);
.class {
z-index: map-get($zindex, z-index-1);
position: relative;
}
Z-index usage
$audioHex: (
1930s : #909195,
1940s : #e60d64,
1950s : #8cc63e,
1960s : #d15238,
1970s : #fdb813,
1980s : #00bbe4,
1990s : #810055,
2000s : #083a81,
2010s : #4c854e
);
@each $key, $value in $audioHex {
.promo-audio .audio-#{$key} {
background-color: $value;
}
}
Decade/Hex Code map
Used in @each loop
Operations
- All standard mathematical operations can be performed
- Must be same unit
- Standard boolean operators
Functions
- Many built in functions
- random($limit)
- saturate($color, $amount)
- if($condition, $if-true, $if-false)
- floor, ceil
- str_index, str_length, str_slice, etc.
Create Functions
$grid-width: 40px;
$gutter-width: 10px;
@function grid-width($n) {
@return $n * $grid-width + ($n - 1) * $gutter-width;
}
.sidebar { width: grid-width(5); }
Control Directives
$boolean: true !default
@mixin simple-mixin
@if $boolean
@debug "$boolean is #{$boolean}"
display: block
@else
@debug "$boolean is #{$boolean}"
display: none
.some-selector
@include simple-mixin
- Expressions for including styles only under some conditions or including the same style several times with variations
- Provide flow and logic in mixins
- !default - gives value unless the variable has an assigned value
- Others include @for, @each, and @while
Control Dir. Ex.
Used on Shedd Aquarium/Ticket Philly
$colorPrimary: #6e7998;
$colorSecondary: #3c1d6d;
$colorTertiary: rgba($colorPrimary, .1);
$colorTint: #d3d6e0;
Each theme has partial file defining these variables:
Import partial; include mixin with name and color variables
@import 'themes/_themeAbout.scss';
@include theme("theme-about", $colorPrimary,
$colorSecondary, $colorTertiary, $colorTint);
@mixin theme($name, $colorPrimary, $colorSecondary, $colorTertiary, $colorTint){
body[data-theme="#{$name}"] {
body:after { background: $colorPrimary; }
h1 { color: $colorPrimary;}
}
@if $name == theme-about {
> div:before { background-image: url(/Global/bg/dropdowns/about-top.gif); }
}
@if $name == theme-animals {
> div:before { background-image: url(/Global/bg/dropdowns/animals-top.gif); }
}
}
Mixin declaration
Cool Stuff
Animate polyhedral expansion:
http://codepen.io/thebabydino/pen/qDziw
Rotating icosidodecahedron:
http://codepen.io/thebabydino/pen/kpCyx
(Relies on Compass - Sass extension that adds helpers)
Resources
Sass
By ehayman
Sass
- 2,160