A collection of tools and patterns that help us quickly create flexible websites.
Examples
Color and White-Space
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quasi unde rerum alias veritatis ducimus? Placeat nesciunt commodi quaerat, nobis doloremque vero temporibus eius explicabo nam ad nisi numquam. Explicabo, tenetur!
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quasi unde <span class="u-color-red-1 / u-white-space-nowrap">rerum alias</span>
veritatis ducimus? Placeat nesciunt commodi quaerat, nobis <span class="u-color-red-1 / u-white-space-nowrap">doloremque vero</span>
temporibus eius explicabo nam ad nisi numquam. <span class="u-color-red-1 / u-white-space-nowrap">Explicabo, tenetur!</span>
</p>
Display
Visible on desktop.
Visible on mobile.
<p class="u-display-none@lt-md">Visible on desktop.</p>
<p class="u-display-none@md">Visible on mobile.</p>
Flexbox
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Quae dolor dolore et, soluta vel officiis aliquid voluptate! Quas expedita rerum ab molestias enim doloribus. Accusantium nobis architecto, quas ratione ex.
<div class="u-display-flex / u-flex-wrap-nowrap / u-align-items-center">
<p class="u-flex-0 / u-padding-right-sm">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
<p class="u-flex-1">Quae dolor dolore et, soluta vel officiis aliquid voluptate! Quas expedita rerum ab molestias enim doloribus. Accusantium nobis architecto, quas ratione ex.</p>
</div>
Grid
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Neque sapiente deleniti, pariatur dolorem harum incidunt quo esse animi excepturi tempore exercitationem alias aliquid delectus ab velit! In officia amet quisquam.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Neque sapiente deleniti, pariatur dolorem harum incidunt quo esse animi excepturi tempore exercitationem alias aliquid delectus ab velit! In officia amet quisquam.
<div class="o-grid o-grid--gutters">
<p class="o-grid__item u-width-1/1 u-width-1/2@md / u-margin-bottom-sm">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Neque sapiente deleniti, pariatur dolorem harum incidunt quo esse animi excepturi tempore exercitationem alias aliquid delectus ab velit! In officia amet quisquam.</p>
<p class="o-grid__item u-width-1/1 u-width-1/2@md / u-margin-bottom-sm">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Neque sapiente deleniti, pariatur dolorem harum incidunt quo esse animi excepturi tempore exercitationem alias aliquid delectus ab velit! In officia amet quisquam.</p>
</div>
Install
npm i --save-dev mode-front-end
Config
npm i --save-dev stylelint-config-property-sort-order-smacss
npm run init-config --prefix ./node_modules/mode-front-end
This adds the following config files your project root:
Starter Kit
npm i --save-dev svg4everybody picturefill lazysizes
npm run init-starter-kit --prefix ./node_modules/mode-front-end
Gulp Tasks (via Elixir)
npm i --save-dev gulp gulp-gzip gulp-responsive laravel-elixir laravel-elixir-imagemin laravel-elixir-livereload laravel-elixir-svgstore laravel-elixir-webpack-official webpack
npm run init-gulp --prefix ./node_modules/mode-front-end
Other Common Packages
npm i --save-dev fontfaceobserver
npm i --save-dev object-fit-images
Style Guide
Naming Conventions
BEMIT
block__element--modifier@breakpoint
Namespaces
o-
Object : Generic styles that can be reused in multiple, unrelated contexts.u-
Utility : “A very specific role [that is] not tied to any specific piece of UI.”c-
Component : “A concrete, implementation-specific piece of UI.”t-
Theme : Use to affect the appearance of components.is-
,has-
State : “Temporary, optional, or short-lived style.”-
_
Hack : The worst (hopefully temporary) styles. js-
JavaScript : Use to bind behaviors to the DOM. (This makes for more flexible styling.)qa-
QA : Use to bind automated UI tests to the DOM. "Basically just reserves hooks in the DOM for non-CSS purposes."
Upgrade Guide
Upgrading to 2.11.3 from 2.3.x
Switching from yarn back to npm
rm yarn.lock
npm i
git add yarn.lock
git add package-lock.json
git commit
Upgrading to 2.3.0 from 2.2.x
Estimated upgrade time: 1–2 hours
Switching from scss-lint to stylelint
Uninstall scss-lint
gem uninstall scss_lint
- Sublime Text > Package Control: Remove Package > SublimeLinter-contrib-scsslint
Install stylelint
npm install -g stylelint
- Install SublimeLinter packages*:
- Sublime Text > Package Control: Install Package > SublimeLinter
- Sublime Text > Package Control: Install Package > SublimeLinter-contrib-stylelint
*Plugins for other text editors are listed here.
To automatically lint and show errors when you save a file:
- Sublime Text > Preferences > Package Settings > SublimeLinter > Settings - User
- Add these options:
{
"user": {
"lint_mode": "load/save",
"show_errors_on_save": true,
}
}
Update project
yarn upgrade mode-front-end
yarn add stylelint-config-property-sort-order-smacss
npm run init-config --prefix ./node_modules/mode-front-end
rm -f .scss-lint.yml
git add .scss-lint.yml && git add .stylelintrc
git checkout .
git commit -m "Replace scss-lint with stylelint"
Use the stylelint CLI to quickly scan the entire project:
stylelint resources/assets/sass/**/*.scss
Upgrading to 2.2.0 from 2.1.x
Estimated upgrade time: 0.5 hour
u-object-fit()
Mixin
Update all u-object-fit()
references so they include an alias:
For example, @include u-object-fit('cover');
becomes @include u-object-fit('cover', cover);
.
If you have any custom .u-object-fit-*
classes, do the same.
For example, if your .u-object-fit-cover { … }
class depends on extra width
and height
styles you can use:
@include u-object-fit('cover-100%', cover) {
width: 100%;
height: 100%;
}
Upgrading to 2.0.0 from 1.3.x
Estimated upgrade time: 4–6 hours
New Browser Support
If your project doesn’t require support for iOS 7, IE 9, or old Android Stock Browsers you can:
- Remove viewport-units-buggyfill
- Update your Browserlist config to IE 10+ and iOS 8+
$gutter
in rem
s
For most dimensions (except media queries) we’re beginning to use rem
s. So, for example, we’ve updated our default $gutter
values to rem
.
Object Mixins
To keep our objects consistent, and to make each object’s structure clear, we’ve decided that every object should use separate mixins for its elements. So we’ve brought back the o-grid__item()
mixin, as well as a few others.
Here are all the objects that require separate element mixins:
Grid
@include o-grid();
@include o-grid__item();
List
@include o-list();
@include o-list__item();
Media
@include o-media();
@include o-media__figure();
@include o-media__body();
Table
@include o-table();
@include o-table__item();
Video
@include o-video();
@include o-video__wrapper();
@include o-video__element();
@include o-video__play();
@include o-video__close();
o-icon()
has max-height
If you have any icon elements without an explicit width/height (e.g., using @include o-icon--size()
), then you may need to double check that the new max-height: 100%;
style doesn’t accidently resize any of your icons.
If this casues issues, you can override the change by adding .o-icon { max-height: none; }
.
o-list()
resets padding-left
In cases where css-reset()
isn’t used, o-list()
now sets padding-left: 0;
.
If this causes issues, you can override the change with a padding utility. For example, @include u-padding('left-40', rem(40));
.
List Modifiers
Several changes have been made to the o-list()
modifiers:
- Rename all plural modifiers to be singular:
o-list--borders()
→o-list--border()
o-list--bullets()
→o-list--bullet()
o-list--commas()
→o-list--comma()
o-list--numbers()
→o-list--number()
o-list--slashes()
→o-list--slash()
- Rename
o-list--numbers-roman()
too-list--roman()
- Add
$alias
and$margin
arguments too-list--bullet()
:- For example,
@include o-list--bullet();
becomes@include o-list--bullet('', 1rem);
- For example,
- If needed, manually add the
top: -2px;
removed from.o-list--bullet > .o-list__item::before
- If needed, manually add the
margin-left: -2px;
and the extra space incontent
removed from.o-list--comma > .o-list__item:not(:last-child)::after
- Add
$alias
and$padding
arguments too-list--disc()
:- For example,
@include o-list--disc();
becomes@include o-list--disc('', 1rem);
- For example,
- If needed, manually add the
padding-bottom: em(6);
removed from.o-list--disc > .o-list__item
- If needed, manually remove the extra space in
content
removed from.o-list--slash > .o-list__item
object-fit()
Mixin
@include object-fit('cover');
requires an argument now, so update any references you had to at least include the default 'cover'
value.
.u-object-fit-cover
and .u-transform-center
Styles
- Replace any
.u-object-fit-cover { … }
styles with the mixin@include u-object-fit('cover');
- Replace any
.u-transform-center { … }
styles with the mixin@include u-transform('center', translate(-50%, -50%));
Replace u-small-caps()
If your project depends on any of the u-small-caps
mixins, you’ll need to copy those back into your project from the source code.
Small caps will be overhauled as an object in a future update, so stay tuned.
u-content()
Mixin
Replace any u-content()
references with either u-content-before()
or u-content-after()
.
u-flex()
Mixin
If you have any custom .u-flex-*
classes, replace them with the new u-flex()
mixin:
For example, .u-flex-1 { … }
becomes @include u-flex('1', 1);
.
u-opacity()
Mixin
Update all u-opacity()
references so they include an alias:
For example, @include u-opacity(50);
becomes @include u-opacity('50', 0.5);
.
u-position()
Mixin
Update all u-position()
references so they include an alias:
For example, @include u-position(1, 2);
becomes:
@include u-position('1/2', absolute, {
left: percentage(1 / 2));
}
If you have any custom .u-position-*
classes, do the same.
For example, .u-position-center { … }
becomes:
@include u-position('center', absolute) {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Width and Height Utilities
- Update all
u-width()
references so they include an alias:- For example,
@include u-width(1, 2);
becomes@include u-width('1/2', percentage(1 / 2));
- For example,
- Update all
u-max-height()
references so they include an alias:- For example,
@include u-max-height(100);
becomes@include u-max-height('100', em(100));
- For example,
- Update all
u-max-width()
references so they include an alias:- For example,
@include u-max-width(100);
becomes@include u-max-width('100', em(100));
- For example,
- Update all
u-min-height()
references so they include an alias:- For example,
@include u-min-height(100);
becomes@include u-min-height('100', em(100));
- For example,
- Update all
u-min-width()
references so they include an alias:- For example,
@include u-min-width(100);
becomes@include u-min-width('100', em(100));
- For example,
Ideally, you should also update any em
values to rem
.
Rename browser-detect
to browserDetect
Update all JS browser-detect
references to browserDetect
:
For example, require('mode-front-end/resources/assets/js/browser-detect/internetExplorer');
becomes require('mode-front-end/resources/assets/js/browserDetect/internetExplorer');
Upgrading to 1.3.0 from 1.2.x
Estimated upgrade time: 0.5 hour
Transfer mode-front-end to madebymode account
If you reference the full URL to mode-front-end anywhere, you’ll need to update it to https://github.com/madebymode/mode-front-end/
Upgrading to 1.0.2 from 0.41.x
Estimated upgrade time: 2–4 hours
Config Files
- In
.editorconfig
set all markup files toindent_size = 2
:- For example,
[*.{html,blade.php}] indent_size = 2
- For example,
- Update
.gitignore
New Build Process
- Use
yarn
to install npm packages - Update
gulpfile.js
with latest tasks:- Replace
responsiveImgs
task withgulp-tasks/responsive-images.js
- Replace
- Replace Browserify with Webpack:
yarn remove browserify browserify-shim laravel-elixir-browserify-official
yarn add laravel-elixir-webpack-official webpack
- Remove Browserify config
- Change
mix.browserify(…);
tomix.webpack(…);
- If needed, add a custom
webpack.config.js
If you want, you can do a clean sweep of all your config and starter kit files by running the new mode-front-end install helpers:
npm run init-starter-kit --prefix ./node_modules/mode-front-end
npm run init-config --prefix ./node_modules/mode-front-end
yarn add gulp gulp-gzip gulp-responsive laravel-elixir laravel-elixir-imagemin laravel-elixir-livereload laravel-elixir-svgstore laravel-elixir-webpack-official webpack
npm run init-gulp --prefix ./node_modules/mode-front-end
Then use git add -p
to pick which changes you want to commit.
.o-section
and .o-grid
Styles
- Replace any
.o-section { … }
styles with the mixin@include o-section();
- Remove all
@include o-grid__item();
mixins (.o-grid__item
styles are included in@include o-grid();
now)
.o-grid__item
Styles
If your styles depend on .o-grid__item
having a default display
and position
, you’ll need to add those styles back:
.o-grid__item {
display: block;
position: relative;
}
Upgrading to 0.41.0 from 0.40.x
Estimated upgrade time: 1 hour
JavaScript Namespaces
- Update any references to
all.js
toindex.js
:- For example,
const dom = require('mode-front-end/resources/assets/js/dom/all');
becomesconst dom = require('mode-front-end/resources/assets/js/dom');
- For example,
Upgrading to 0.31.0 from 0.30.x
Estimated upgrade time: 1 hour
.o-grid
Styles
- Replace any
.o-grid { … }
styles with the mixin@include o-grid();
- Replace any
.o-grid__item { … }
styles with the mixin@include o-grid__item();
Upgrading to 0.27.0 from 0.26.x
Estimated upgrade time: 1–2 hours
Normalize.css and Reset Styles
- Replace Normalize.css with the mixin
@include css-normalize();
- Replace reset styles with the mixin
@include css-reset();
.o-grid
Styles
- Rename all
o-grid__cell
references too-grid__item
:- For example,
<div class="o-grid__cell"></div>
becomes<div class="o-grid__item"></div>
- For example,
We decided to use “item” as a standard element name (e.g., o-list__item
).