author: orionrush@gmail.com | 28.04.19
css/
- app.css
scss/
| |
| |– tools/
| | |– _colors.scss
| | |– _functions.scss
| | |– _fonts.scss
| | |– _grid.scss
| | |– _mixins.scss
| | |– _variables.scss
| | |– _zindex.scss # See smashing mag article below
| | ...
| | |– layers/
| | |– _b_{base}.scss # Base Layer (including reset, typography rules, framework etc)
| | |– _l_{layout}.scss # Layout Layer (basic layout for ideal pages posts etc, followed by specific page overrides)
| | |– _o_{object}.scss # Object Layer (atoms molecules organisms - buttons, .hero-unit .card-preview .top-nav ect.)
| | |– _u_{utility}.scss # Utility Layer (utility classes .font-small etc, the only place where !important is allowed)
| | |– _v_{vendor}.scss # Vendor Layer
| |
| |– _media-queries.scss # @media rules
| |– _tools.scss # third-party tools
| |– _vendor/ # third-party styles
| | |– tachyons etc
| |
| |- vendors-public.scss # imports for public
| |- vendors-app.scss # imports for app
| |
| |– shame/
| | |– _shame.scss # All the bits you're embarrassed about, @*$£*%$ just work! important! all the bits!
| |
| |– main-public.scss
| |- main-app.scss # primary Sass file
A Note on vendor styles: As seen above there is a directory for third party style sheets (plugin's etc.) as well as
_vendors-app.scss
andvendors-public.scss
importer files. This approach was taken due to the sprawl of imported 3rd party styles that was starting to form in themain-*.scss
file.
Notes:
For rapid prototyping, we use Tachyon's built in classes. However as the design/prototyping becomes more stable, we transition reusable collections to flat, low specificity selectors, following an adapted versions of BEM conventions, with Atomic Design components: ABEM.
Version Number Prefix v{X}-
followed by:
Capitalised Prefix / {o}rganism- / {m}olecule- / {a}tom-
Which translates to:
.v{X}-{a}-{blockName}__{elementName}
Strictly following BEM conventions could result in monstrously long modifiers, so we use a distinct class instead, with an explicit -is-
like so:
.-is-{modifierName}
In SASS we can be efficient and use nesting rules:
.v1-O-blockName {
&__elementName {
&.-is-modifierName {
/* modifier styles go here */
}
}
}
Notes:
@mixins``(@include)
will insert css where ever they appear - can be sussed with $arguments
.
@mixin awesome($w: 100%, $h: 100%) {
width: $w;
height: $h;
}
body {
@include awesome(960px);
}
p {
@include awesome;
}
Becomes:
body {
width: 960px;
height: 100%;
}
p {
width: 100%;
height: 100%;
}
The down side of @mixins
is that can dump a large amount of duplicate css all over your style sheet - ie not very DRY. However, while this isn't pretty, gzipping does an excellent job of compressing duplicate lines of text, so the size penalty is mitigated.
@extend
.awesome {
width: 100%;
height: 100%;
}
body {
@extend .awesome;
}
p {
@extend .awesome;
}
Becomes:
.awesome, body, p {
width: 100%;
height: 100%;
}
@extend
can be used to share properties between elements. However, we should generally avoid extending classes as they can unnecessarily bloat the size of our style sheet and sometimes create a whole range of bizarre specificity issues.
However, when used with silent classes
aka placeholders
@extend
becomes a very powerful tool.
Placeholders:
.awesome, %awesome {
width: 100%;
height: 100%;
}
body {
@extend %awesome;
}
p {
@extend %awesome;
}
Becomes:
body, p {
width: 100%;
height: 100%;
}
The rules to follow when using @extend
with silent classes/pointers are as follows:
Notes:
NOTE: SASS hazards with variables:
Before we proceed, it must be noted that in SASS, the FIRST declaration of a var is king. Subsequent declarations cannot override previously declared values. Because of this, the import order is very important! Basically frameworks need to be toward the bottom of your import tree, and your overriding variable declarations near the top.
// main.css
// Overriding variables (duplicating the framework vars in question)
@import “theme/variables”;
// Importing Bootstrap-Sass
@import “../bootstrap/assets/stylesheets/bootstrap”;
// and so on....
Using @extend
with with silent placeholder classes and our ABEM conventions:
<article class="pb4">
<div class="mw9 center tc-m">
<h1 class="f4 fw6 lh-title f1-ns">
H1 heading
</h1>
<div>
...
<div>
</div>
</article>
... *becomes*
<article class="v1-o-pageArticle">
<div class="v1-o-pageArticle_wrap ">
<h1 class="v1-a-articleHeading">
H1 heading
</h1>
<div>
...
<div>
</div>
</article>
...
.v1-o-pageArticle {
@extend %pb4;
&__wrap {
@extend %mw9;
@extend %center;
@extend %tc-m;
.v1-a-articleHeading {
@extend %f4 ;
@extend %fw6;
@extend %lh-title;
@extend %f1-ns;
}
}
}
// See note on breakpoint specific rules -l -m -ns etc.
@media #{$breakpoint-medium} {
article div {
@extend %tc-m;
}
}
@media @media #{$breakpoint-not-small} {
article div h1 {
@extend %f1-ns;
}
}
While this may seem more verbose in our style sheet, it is the first step in making the project, framework agnostic, and at the same time using @extend
with placeholders is a very powerful tool.
To this end we have created a fork of the original Tachyons SASS project, where we have added placeholders to all of the project classes. This fork can be found at: https://github.com/orionrush/tachyons-sass/tree/pointers
Note: placeholders that are declared in @media
breakpoint rules, cannot be extended outside of the same rule.