Here lies Mixd's framework for beginning any front end build — containing HTML, Sass & CSS files, jQuery and a pattern/module library. Users of this framework should follow the guidelines below which complement its architecture, based around Jonathan Snook's SMACSS and Jake Archibald's Sass-IE concept.
- This work is licensed under a Creative Commons Attribution-NonCommercial 3.0 Unported License
- You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work)
This framework makes use of the following external libraries or services
- Normalize.css
- Griddle
- Fontello
- jQuery
- Modernizr
- Selectivizr
- jQuery Placeholder
- FitVids
- ExpandingTextareas
- This is a mobile-first framework
- This framework uses Sass to generate CSS
- All site assets must be placed within the
/assets/
folder - Working
.scss
/ Sass files are found in the/assets/scss
folder - All primary styles are placed in the
/core
folder - HTML Classes follow BEM naming conventions
- Practise OOCSS principles and never be afraid to use CSS classes where appropriate
/assets/scss
- We recommend CodeKit as a compiler for Mac
- Directly compiled stylesheets sit at root level, with all other separations inside sub folders
- CSS must compile to the
/assets/css
folder and will be minified/compressed upon launch - Helper mixins have been provided in the
/config
folder undermixins.scss
— to speed up development in common areas e.g. outputtingbackground-image
gradients with all vendor prefixes - Utilise these as you see fit or consider using Compass for more comprehensive mixins libraries
/assets/scss/config
- This is a good starting point
- Global variables are set in
vars.scss
e.g. colours, font families etc. Place any variables you create during the project here - Major breakpoints are managed centrally here using the convention
$bp1
,$bp2
etc. - Mixins are defined in
mixins.scss
. Place any mixins you create during the project here under Project-Specific Mixins
- Write
@media
declarations in context using the methods outlined in Sass-IE - Keeping
@media
queries per selector allows for easier maintenance and extaction of modules respond-min
andrespond-max
mixins have been provided inutils.scss
to easily createmin
andmax
media queries from inside selectors, allowing nesting- Create breakpoints when content requires, not based on device or screen size
- Always set breakpoints in
ems
for fexibility - Reference all major breakpoints using the corresponding
$bp
variable - Use minor breakpoints as you see fit on a case-by-case basis
- Work primarily mobile-first, unless using a
max-width
query will bring significantly leaner code and it does not contain any background images or fonts - Never separate media queries into their own stylesheet/per breakpoint
- Keeping to this process is vital due to how the framework compiles styles for old Internet Explorer
.media__img {
// global syles
margin-bottom: 1.5em;
// at major breakpoint 1
@include respond-min($bp1) {
float: left;
margin-bottom: 0; }
// at a different, minor breakpoint
@include respond-min(39em) {
float: right; }
}
Although this framework doesn't strictly follow the SMACSS categorision pattern, it is heavily infuenced by it's methodology. As long as you stick to the practices set out in SMACSS, you won't go wrong.
Contrary to to guidelines set out in SMACSS, this framework does not include theme
and state
stylesheets, instead these abstractions should be included with modules.scss
in a logical cascading order. This helps keep all modular code in context whilst maintaining the cascading benefits of the SMACSS method.
- /assets/scss/core/base.scss
- Normalize.css is used to create consistency across all browsers
- Project Defaults are set as reasonable starting point, but should be changed if required
- Use Fontello to compile your icon font with project-specific glyphs
- When exporting, name the font "Fontello" and upload all font files to
/assets/fonts
- Paste icon codes/classes taken from
Fontello-codes.css
in the downloaded zip file, intotheme.scss
- Icon classes should be prefixed with
.icon-
- The classes
.icon-large
and.icon-pad
can be used to extend icons - The
.icon
class can be@extended
when adding a class isn't reasonable e.g. on lots of<li>
's
- /assets/scss/core/layout.scss
- Layout rules define major content areas or layout components e.g. header, container or grids
- Layout is reserved for layout components only and should only be styled as such
This framework uses Nicolas Gallagher's Griddle for layout. Grids are created at each breakpoint within layout.scss
and defined using classes on each grid column to determine which proportion is taken at which breakpoint e.g.
<div class="grid">
<article class="grid__cell unit-1-2--bp2 unit-1-3--bp4">
<h3 class="zero--top">one of three</h3>
<p>This unit is one-of-two after $bp2 and one of 3 after $bp4.</p>
</article>
<article class="grid__cell unit-1-2--bp2 unit-1-3--bp4">
<h3 class="zero--top">one of three</h3>
<p>This unit is one-of-two after $bp2 and one of 3 after $bp4.</p>
</article>
<article class="grid__cell unit-1-2--bp2 unit-1-3--bp4">
<h3 class="zero--top">one of three</h3>
<p>This unit is one-of-two after $bp2 and one of 3 after $bp4.</p>
</article>
</div>
- /assets/scss/core/modules.scss
- This is where the bulk of your CSS will go and contains objects & modules
- Objects are abstractions, created as classes to provide one re-useable element of styling e.g.
.nav--inline
turns lists inline - Modules are an extension of objects but are more specific parts of a page e.g.
.nav--tertiary
. The two are used/work together - Modules sit inside layout components and can be moved to a different part of the page without breaking
- When building modules consider existing objects, future reuse and create abstractions if necessary
- Don't modify a base object once created. Either extend it for your module or don't use it
- Always use classes (never IDs) to define modules.
- Always define background, typography, colour and other 'theme' styling as separate abstractions after thier related module
- Always define element states such as
:hover
and:focus
after both the module and theme styles
- Navigation objects
.nav-inline
,.nav-divided
and.nav-stacked
are supplied by default, referencing mixins inmixins.scss
.media
and.island
objects are also included
- Modules should contain all
@media
declarations in context, nested within each module - This allows a developer to instantly see how a modules changes, with one point of reference for layout in
modules.scss
and one for theme intheme.scss
- Utilise mixins to create abstractions and re-include these at a given breakpoint, rather than redefining them
// this object turns lists inline
@mixin nav-inline {
li,
a {
display: inline-block;
*display:inline;
zoom:1; }
}
// object class
.nav-inline {
@include nav-inline; }
// tertiary navigation module
.nav-tertiary {
// global syles
margin-bottom: 1.5em;
// turn .nav-tertiary to an inline list at breakpoint 2
@include respond-min($bp2) {
@include nav-inline;
}
}
// this object turns lists inline
.nav-inline {
li,
a {
display: inline-block;
*display:inline;
zoom:1; }
}
// tertiary navigation module
.nav-tertiary {
// global syles
margin-bottom: 1.5em;
// turn .nav-tertiary to an inline list at breakpoint 2
@include respond-min($bp2) {
li,
a {
// redefining what's above
display: inline-block;
*display:inline;
zoom:1; }
}
}
- /assets/scss/libs/mixd-modules.scss
- The Mixd Module Library contains mixins for common modules and details of accompanying markup
- Should you produce any potentially reuseable/useful modules, update this file in the master repository after project completion
- This allows for greater reuse of code between projects.
- Modules should only contain structure and layout (defined by explicit CSS properties) with no theme styles
- Theme for each module can then be added on a per-project basis, with a full view of that project's cascade prior to styling
- If necessary, include any mixins used within a module so it can be added to any new project without missing dependencies
- When using new modules check for existing mixins and/or refactor if necessary
/* List Block
----------------------------------*/
// useful object mixin
@mixin list-two-cols {
li {
float: left;
width: 50%; }
}
// Module
.list-block {
@include respond-min($bp1) {
// change list to two columns at breakpoint 1
@include list-two-cols;
}
}
- /assets/scss/libs/overrides.scss
- Contains helper classes and style trumps which will always want to override previously defined styles.
- Helper Classes are used to alter global typographic styles when required or unset defaults e.g.
.list-unset
removeslist-style
andmargin-left
from any<ul>
or<ol>
- Style trumps are used when you want to globally override and elements style, e.g. error states which would always be displayed in red.
!important
is used often here, as you'll always want these rules to trump out previously defined rules.
- /assets/scss/core/cms.scss
- CMS styles are specific to the CMS (here, WordPress) being used including any plugins
- If using WordPress, add a
.wp-content
class to the containing element of<?php the_content(); ?>
- /assets/scss/core/modernizr.scss
- Modernizr styles offer fallbacks for non-supporting browsers
- Use
.no-
selectors (always code for better browsers first) - Utilise Sass nesting for browser capabilities
.no-svg {
.logo {
/* styles */ }
.sprite {
/* styles */ }
}
- /assets/scss/all-old-ie.scss
- IE8 and below is served styles via
all-old-ie.scss
- Styles are compiled automatically with media queries stripped-out
- Set which layout you want old IE to take using the
$mqs-up-to
variable inall-old-ie.scss
- Never polyfill IE with media query support
- Add additional IE styles/fixes to the bottom of
all-old-ie.scss
using relevant classes on the<html>
element - A print stylesheet
print-old-ie.scss
is created for IE, containing global typographic/layout styles. These are then overwritten byprint.css
as per modern browsers, meaning you only have to worry about working with one print stylesheet - Utilise Sass nesting for browser versions
.lt-ie9 {
.fix {
/* styles */ }
.another-fix {
/* styles */ }
}
- Always aim for resolution independence, using SVG images, icon fonts and CSS wherever possible
- Compile all images in a sprite and utilise the
sprite
mixin - When using SVG, code for better browsers first and provide fallbacks using Modernizr
- /assets/js/scripts.js
- Plugins are stored in a separate file
assets/js/plugins.js
and imported intoscripts.js
using Codekit. - To minimise http requests, do not load-in any additional JavaScript files. Use codekit to include partials into
scripts.js
. - Modernizr is included to determine browser capabilities and provide appropriate fallbacks
- Selectivizr is included to add attribute/pseudo selector support in old IE
- Other plugins in operation by default are jQuery Placeholder, FitVids and ExpandingTextareas
- patterns.html
- The Mxd Pattern Library contains markup for common modules or components used within projects
- Check here before writing markup to see if you can reuse an existing module
- Should you produce any potentially reuseable/useful markup, update this file in the master repository after project completion
- This allows for greater reuse of code between projects.
Listen below are some general rules to adhere to when using this framework or when completing any front end work. Extracts are taken from CSS Guidelines written by Harry Roberts.
Use multi-line CSS to help with version control (diffing single line CSS is a nightmare) and order CSS declarations by relevance, not alphabetically.
Always use a trailing semi-colon on the last declaration in a ruleset to avoid any potential confusion and syntax errors over the life of the document.
Here is the preferred convention and structure for defining CSS rules, comments and nested elements within Sass:
/* Tertiary Nav
----------------------------------*/
.nav--tertiary {
a {
padding: 0 .75em; }
:first-child a {
padding-left: 0; }
}
/* Blocked Nav Object
----------------------------------*/
.nav--blocked a {
display: block;
padding: .5em; }
The framework uses the BEM methodology for class naming. The notation used in this framework is heavily influenced by Harry Roberts' MindBEMding article.
- Use single hyphens to deliminate blocks:
.thisIsBad{}
,.this_is_also_bad{}
but.this-is-correct{}
. - Use double underscores for descendants of a block i.e.
.block__element
. - Use double hyphens for block modifiers i.e.
.block--modifier
.media{} /* Block */
.media__img /* Element */
.media--flipped /* Modifier */
- bem.info
- csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/
- nicolasgallagher.com/about-html-semantics-front-end-architecture/
Comment as much as you can as often as you can. Where it might be useful, include a commented piece of markup which can help put the current CSS into context.
Be verbose, go wild, CSS will be minified before it hits live servers.
When building a new component write markup before CSS. This means you can visually see which CSS properties are naturally inherited and thus avoid reapplying redundant styles. Look for existing modules or objects to work with before beginning and always comment a new module with a title.
When building components try and keep a DRY, OO frame of mind. Adding classes is not a crime - use them wisely and efficiently.
Instead of building dozens of unique components, try and spot repeated design patterns abstract them; build these skeletons as base objects and then peg classes onto these to extend their styling for more unique circumstances.
If you have to build a new component split it into structure (modules) and skin (theme); build the structure of the component using very generic classes to reuse that construct and then use more specific classes to skin it up and add design treatments.
- csswizardry.com/…/the-nav-abstraction
- stubbornella.org/…/the-media-object-saves-hundreds-of-lines-of-code
All components should be left totally free of widths; your components should always remain fluid and their widths should be governed by a grid system.
Heights should never be be applied to elements. Heights should only be applied to things which had dimensions before they entered the site (i.e. images and sprites). Never ever set heights on <p>
s, <ul>
s, <div>
s, anything. You can normally achieve the desired effect with line-height
which is far more flexible.
Grid systems should be thought of as shelves. They contain content but are not content in themselves. You put up your shelves then fill them with your stuff.
You should never apply any styles to a grid or layout container, they are for layout purposes only. Nest modules inside layout components.
Never use pixels unless unavoidable. Use a combination of ems
, rems
and percentages. Only use rems
if you need to reference a base measure e.g. to make padding equal more easily
Set a relevant default font-size on the <html>
element to supply global typographic elements. From there, use ems
to define font sizing — do not define any font sizes in pixels. Define line heights unitlessly everywhere unless you are trying to align text to known heights.
Do not use rems
for font-sizing unless absolutely necessary due to compound nesting. If using rems
- provide pixel/<em>
fallback for IE using the Modernizr .no-remunit
class.
Avoid defining font sizes over and over; to achieve this have a predefined scale of font sizes tethered to classes. Recycle these rather than having to declare styles over and over.
Before writing another font-size declaration, see if a class for it already exists.
It might be tempting to use declarations like background: red;
but in doing so what you are actually saying is I want no image to scroll, aligned top left and repeating X and Y and a background colour of red. Nine times out of ten this won't cause any issues but that one time it does is annoying enough to warrant not using such shorthand. Instead use background-color: red;
.
Similarly, declarations like margin: 0;
are nice and short, but be explicit. If you're actually only really wanting to affect the margin on the bottom of an element then it is more appropriate to use margin-bottom: 0;
.
Be explicit in which properties you set and take care to not inadvertently unset others with shorthand. E.g. if you only want to remove the bottom margin on an element then there is no sense in blitzing all margins with margin: 0;
.
Shorthand is good, but easily misused.
Keep selectors efficient and portable.
Heavily location-based selectors are bad for a number of reasons. For example, take .sidebar h3 span {}
. This selector is too location-based and thus that span
cannot be moved outside of a h3
outside of .sidebar
and maintain styling.
Selectors which are too long also introduce performance issues; the more checks in a selector (e.g. .sidebar h3 span
has three checks, .content ul p a
has four), the more work the browser has to do.
Make sure styles aren't dependent on location where possible, and make sure selectors are nice and short.
Remember: classes are neither semantic or insemantic; they are sensible or insensible! Stop stressing about semantic class names and pick something sensible and futureproof.
An over-qualified selector is one like div.promo
. You could probably get the same effect from just using .promo
. Of course sometimes you will want to qualify a class with an element (e.g. if you have a generic .error
class that needs to look different when applied to different elements (e.g. .error { color: red; }
div.error { padding: 14px; }
), but generally avoid it where possible.
Another example of an over-qualified selector might be ul.nav li a {}
. As above, you can instantly drop the ul
and because .nav
is a list, any a
must be in an li
— getting ul.nav li a {}
down to just .nav a{}
.
Instead of using selectors to drill down the DOM to an element, it is often best to put a class on the element you explicitly want to style. Let's take a specific example.
Imagine you have a promotional banner with a class of .promo
and in there there is some text and call-to-action link. If there is just one a
in the whole of .promo
then it may be tempting to style that call-to-action via .promo a {}
.
The problem here should be obvious in that as soon as you add a simple text link (or any other link for that matter) to the .promo
container it will inherit the call-to-action styling, whether you want it to or not. In this case you would be best to explicitly add a class (e.g. .cta
) to the link you want to affect.
Be explicit; target the element you want to affect, not its parent. Never assume that markup won't change.
You should never find yourself writing selectors whose key selector is a type selector (e.g. .header ul {}
) or a base object (e.g. .header .nav {}
). This is because you can never guarantee that there will only ever be one ul
or .nav
in that .header
, the key selector is too loose/too broad.
It would be more appropriate to give the element in question an explicit class targeting that one and that one only, so .header .nav {}
would be replaced with .site-nav
, for example.
The only time where a type selector may be appropriate is if you have a situation like this:
a {
color:red; }
.promo {
background-color: red;
color: white; }
.promo a {
color: white; }
In this case you know that every a
in .promo
needs a blanket rule because it would be unreadable without.
Write selectors that target what you want, not what happens to be there already.
Do not use IDs in CSS at all. They can be used in your markup for JS and fragment-identifiers but use only classes for styling. Do not use a single ID in this (or any other) stylesheet.
Classes come with the benefit of being reusable and they have a nice, low specificity.
It is okay to use !important
on helper classes only. To add !important
preemptively is fine, e.g. .error { color: red !important; }
, as you know you will always want this rule to take precedence.
Using !important
reactively, e.g. to get yourself out of nasty specificity situations, is not advised. Rework your CSS and try to combat these issues by refactoring your selectors. Keeping your selectors short and avoiding IDs will help out here massively.
A magic number is a number which is used because it just works. These are bad because they rarely work for any real reason and are not usually very futureproof or flexible/forgiving. They tend to fix symptoms and not problems.
For example, using .dropdown-nav li:hover ul { top: 37px; }
to move a dropdown to the bottom of the nav on hover is bad, as 37px is a magic number. 37px only works here because in this particular scenario the .dropdown-nav
happens to be 37px tall.
Instead use .dropdown-nav li:hover ul{ top: 100%; }
which means no matter how tall the .dropdown-nav
gets, the dropdown will always sit 100% from the top.
Every time you hard code a number think twice; if you can avoid it by using keywords or aliases (i.e. top:100%
to mean all the way from the top) or — even better — no measurements at all then you probably should.
Every hard-coded measurement you set is a commitment you might not necessarily want to keep.
If you run into a CSS problem take code away before you start adding more in a bid to fix it. The problem exists in CSS that is already written, more CSS isn't the right answer!
Delete chunks of markup and CSS until your problem goes away, then you can determine which part of the code the problem lies in.
It can be tempting to put an overflow: hidden;
on something to hide the effects of a layout quirk, but overflow was probably never the problem; fix the problem, not its symptoms.