Introduction
This site is meant to help us unify our front-end code. These are the documented best-practices for front-end code structure.
CSS Background
background, background-color, background-image, background-position, background-repeat, background-size
background
is one of the most common properties we set. It can be used shorthand or broken out into more specific properties.
Set a background color
When setting a background color, use background: $light-grey
. Even when overriding for something like a hover state, still just use background
, rather than background-color
.
Set a background image
Using an image as a background can be complicated. The easiest way to do this, without digging in too much, is to set the background-image: url()
and use the provided mixin.
Example
// Here's the mixin
@mixin background-image(){
background-repeat: no-repeat;
background-size: cover;
background-position: center center;
}
// Here's how to use it
.element {
background-image: url('.../image.jpg');
@include background-image();
}
Using this method, you can also set a fallback image by having multiple values in the background-image
. This is helpful when you’re not hosting the source of the image you want to set.
Example
.element {
background-image: url('http://twitter.com/.../avatar.jpg'), url('.../backup-image.jpg');
@include background-image();
}
background-size: cover vs. contain
background-size: cover
will stretch the image to cover the entire element, no matter the proportions, but it will keep the image’s original aspect ratio.
background-size: contain
will constrain the image to fit within the bounds of the element, but will always keep the entire image visible.
CSS Box Model
The Box-model is the basis for the strucure of elements on the web. Elements are defined in space by firstly their display-type, then their width and height, followed by other attributes such as padding, margin, and border.
box-sizing
In the original design of the box-model, padding, margin, and border units would add to the size of the div. (That’s the old way)
In the new way (using box-sizing: border-box;
), padding and border push into the set dimensions of the div. This allows for much easier calculations and control of element spacing.
Here’s a live Codepen example: http://codepen.io/shaunrfox/pen/raojBW/
width
EXAMPLE VALUES: 100%
, 200px
, calc(100% - 50px)
width
is very straightforward, but the most important thing to keep in mind is scalability on different screen sizes and when the browser window is resized.
To accomodate the different environments that a site could be viewed in, favor setting percentage-based widths.
Any percentage-based width used is going to be relative to the element’s parent.
calc()
is usually used to make something fill a space, minus a pixel value. For instance having a scrollable area, minus the header. Make sure to leave a single space on either side of your operator or it won’t work.
height
EXAMPLE VALUES: 100%
, 200px
, calc(100% - 50px)
height
is considered in much the same way as width
, but is not as often set as a percentage (besides 100%).
Any percentage-based height used is going to be relative to the element’s parent.
calc()
is usually used to make something fill a space, minus a pixel value. For instance having a scrollable area, minus the header. Make sure to leave a single space on either side of your operator or it won’t work.
padding
EXAMPLE VALUES: 20px
In the new box-model mode (box-sizing: border-box;
), padding will push into the element.
padding
can be defined on four sides of an element, like many things: top, right, bottom, left. This can be done as a shorthand or as individual values.
.my-class {
padding: 10px 20px 30px 0;
/* top: 10px, right: 20px, bottom: 30px, left: 0 */
}
// or
.my-class {
padding-top: 20px;
padding-left: 40px;
}
margin
EXAMPLE VALUES: 20px
, 0 auto
margin
is always outside of the dimensions of your element and set the space around the element, relative to it’s neighbors. This being the case, be especially careful not to cause layout collisions. This happens a lot when combining margin with percentage-based widths.
A common trick for horizontally centering an element inside a larger parent is to set margin: 0 auto;
. The 0
defines the top and bottom margin (a shorthand), and the auto
defines the right and left. It should be noted that this only works if the element also has a width set.
.parent-element {
width: 100%;
height: 100%;
}
.child-element {
width: 400px;
height: 300px;
margin: 0 auto;
}
border
EXAMPLE VALUES: 1px solid $light-grey
border
is defined similar to padding and can be treated nearly the same. It can be defined on all sides at once or as individual attributes.
We most commonly use the shorthand definitions listed below, but they can also be broken out on their own. The second example is also a common way we use it, defining multiple values as shorthand, but then overriding specific ones for an interaction or emphasis.
.element {
border: 1px solid $light-grey;
}
.other-element {
border-bottom: 1px solid $white;
&:hover {
border-color: $blue;
}
}
border-radius
EXAMPLE VALUES: 4px
, 50%
border-radius
affects the corners of things. It can be used to give subtle rounded-corners to things like buttons, or to make element corners completely round (border-radius: 50%
), forming a circle, for things like avatar images.
It can be defined shorthand as top-left, top-right, bottom-right, bottom-left, or as individual values.
CSS Box-Shadow
CSS Cursor
CSS Display
EXAMPLE VALUES: inline
, block
, inline-block
, table
, none
“Every element on a web page is a rectangular box. The display property in CSS determines just how that rectangular box behaves.” —CSS Tricks
https://css-tricks.com/almanac/properties/d/display/
display: inline;
These elements are things that behave like text. They’re primarily relative to a baseline and don’t have much ability to affect the layout of other elements on the page.
While many elements’ default state is inline, it’s not something that we set as an override very often, since we’re mostly wanting to deal with boxy things.
display: block;
These elements are things like <div>
and <section>
. They will behave like rectangles and they’re the building blocks of web layouts.
The default width for block
elements is 100%, so they will stretch to the extent of their parent’s width.
display: inline-block;
This is kind of a mix of the two above. You can set some of the same “physical” characteristics of block
, but the element is still relative to a baseline (of text, for instance).
The default width for inline-block
elements is relative to the element’s contents.
If you want to center an element using inline-block
, you must set text-align: center
on it’s parent.
display: table
This can be used to make regular block elements behave more like a table. For example, a parent element can be set to display: table;
and it will have children set to display: table-row;
and display: table-cell;
. This can be especially helpful when you need to display tabular data but also need to support a responsive environment.
Try to limit use of display: table
unless you’re showing tabluar data.
display: none
The easiest way to hide elements on the page.
CSS Layout
position
EXAMPLE VALUES: relative
, absolute
, fixed
The position property manipulates the location of an element. Each value of this property will affect the element in a different way.
static
static
is the default position value of all elements on the web. If you don’t set the position explicitly, this is the position your element has.
relative
relative
positioning will layout relative to it’s normal position. You can affect the position of the element by adding additional positioning properties, like top
, right
, bottom
, left
, and z-index
. This will remain in the flow of other elements on the page.
absolute
absolute
positioning is always relative to it’s closest parent with relative
positioning. This will also be pulled out of the normal flow of the page, so it can overlap other elements.
fixed
fixed
positioning is always relative to the viewport, meaning it always stays in place, even when the page is scrolled. This is rarely used except sometime for things like headers, footers, or modals.
top, right, bottom, left
EXAMPLE VALUES: 0
, 100%
, -20px
These properties are used in conjunction with relative
, absolute
, or fixed
positioning.
.parent-element {
position: relative;
}
.child-element {
position: absolute;
top: 20px;
left: 20px;
// 20px from the top, left corner of it's parent, regardless of padding or other sibling elements.
}
z-index
EXAMPLE VALUES: 1
, -1
, 25
The z-index property in CSS controls the vertical stacking order of elements that overlap. As in, which one appears as if it is physically closer to you. z-index only effects elements that have a position value other than static (the default). —CSS-Tricks
Be both conscious and sensible with your z-index values. Avoid tacking on lots of zeros, but also leave yourself room to fill in between values if you need to.
float
EXAMPLE VALUES: left
, right
, none
float
is usually used when you want two or more block elements to be side-by-side. It’s easiest to see in a visual example: http://codepen.io/bxyoung89/pen/WbLRve
clear
If you float things, the parent is not aware of their height. Using a clear fix solution forces the parent to respond to the height of it’s children.
You should use our handy mixin: @include clearfix();
transform
EXAMPLE VALUES: translateY(-50%)
You can do a lot of things with transform, but usually we only use it for vertical centering. You should be careful with this property because it does not necessarily respect round pixel values and can cause things to become blurry.
Our mixin: @include vertical-align();
will vertically center a block element with unknown height inside a parent that’s larger (most of the time). (not to be confused with the vertical-align
property)
More info here: https://css-tricks.com/centering-css-complete-guide/
vertical-align
This is primarily used for aligning a collection of elements with display: inline-block;
. You’ll usually set this to top
so that the elements’ tops all line up.
CSS Opacity
CSS Overflow
CSS Primer
.class
, block
, inline-block
, table
, none
inline
, block
, inline-block
, table
, none
background
, background-color
, background-image
, background-position
, background-repeat
, background-size
position
, z-index
, top
, right
, bottom
, left
, float
, clear
, vertical-align
, transform
width
, height
, padding
, margin
, border
, box-sizing
font-family
, font-weight
, font-size
, font-style
, line-height
, letter-spacing
, text-align
, text-transform
, text-decoration
, color
:before
, :after
:hover
, :active
, :disabled
, :first-child
, :last-child
, :nth-child
pointer
, default
auto
, scroll
, hidden
1
, 0.8
, 0.2
, 0
How to Center Things
Centering things in CSS can be one of the most challenging parts of understanding CSS. CSS Tricks has a good roundup of the usual methods for centering just about anything:
Centering in CSS: A Complete Guide, by CSS Tricks
Here’s also an example of how to center using “table” styling (used for very specific situations): http://codepen.io/shaunrfox/pen/ZYMzpL/
CSS Pseudo Elements
:before & :after
Every element on the web that can contain content (not img, input, br, hr, etc.) can be given additional pseudo elements.
:before
will put it’s content before all of the parent’s children.
:after
will put it’s content after all of the parent’s children.
Carrot Dangler
This is used to make a small arrow that points to another element. We typically use this for special tooltips or dropdowns. You can see this more easily in the Codepen Example.
.parent-element {
position: relative;
// Must set position for the carrot to work
&:before,
&:after {
content: ''; // IMPORTANT: pseudo elements will not display at all unless the content attribute is set. If you don't want any text, use the empty string.
display: block;
position: absolute;
left: 50%;
}
&:before {
top: -12px;
margin-left: -12px;
border-bottom: 12px solid $light-grey;
border-right: 12px solid transparent;
border-left: 12px solid transparent;
}
&:after {
top: -10px;
margin-left: -10px;
border-bottom: 10px solid $white;
border-right: 10px solid transparent;
border-left: 10px solid transparent;
}
}
CSS Pseudo Selectors
:hover, :active, :disabled, :first-child, :last-child, :nth-child
CSS Selectors
CSS selectors apply styling to all elements that match the given criteria.
In CSS, specificity and order matters. The most specific match will always apply it’s styles, and if there’s a tie, the last in the source-order will win.
.class
This is the most common way to attach styling to an element. Creating a good system for your class name scheme will help avoid collisions and provide clarity for everyone on the project.
Element
This selector will affect all matching elements. For example, the css selector div
will affect all <div>
elements.
Attribute selectors
Sometimes it might be necessary to select elements based on their attributes if a class selector is not appropriate. Here are the most common use cases that we run into.
input[type=”text”]
This is used to target all inputs with their type attributes set to “text”.
data-
HTML allows custom attributes beginning with data-
. One example of where you could use this would be for a custom tooltip where you set data-tooltip
to be the content. Beware that this technique is not the best for accessibility or internationalization.
[class=”ico-*”]
This is a special selector that will allow you to target classes that are prefixed or suffixed with a set naming scheme. The Fox Icons are a good example of this.
Combining Selectors
Now that you know about the two basic selectors, there are various ways we can combine selectors to be more specific, or be more efficient.
selector, selector
To keep your code DRY, you can list selectors that will share the same attributes. You do this by putting all selectors in a comma separated list.
.class-1.class-2
For an element that has multiple classes, the selector can be written: .class-1.class-2
. It’s important to note that this selector is more specific then either classes on their own. If you use a property that has been defined on either of the individual classes, this new selector will override it. If there are properties that are unique to any of the selectors, that property will not be overridden. The determination of how these rules are applied is called “cascading”.
selector selector
Adding a space between selectors targets the first selector’s children, who match the second selector.
Example:
<div class="class-1" id="div-1">
<div class="class-2" id="div-2"></div>
<div class="class-2" id="div-3"></div>
</div>
<div class="class-2" id="div-4"></div>
.class-1 {
background: red;
}
.class-2 {
background: blue;
}
.class-1 .class-2{
background: green;
}
In this example, div-1 will be red. div-2 and div-3 will be green. div-4 will be blue.
selector > selector
This rule is similar to selector selector
, except it only selects the direct descendents, but will not go any further down the hierarchy.
SCSS
This section will cover selectors in SCSS. To read more about SCSS in gerneral, see the SCSS Primer.
nesting
In SCSS, you can nest selectors to logically scope rules, but this should be used cautiosly to avoid making too many overly-specific selectors when they’re compiled.
Nesting Example:
.box {
background: red;
.header {
background: blue;
}
}
Compiled:
.box {
background: red;
}
.box .header {
background: blue;
}
&
As you can see from the previous example, nesting introduces a space between the two rules. Often, though, you’ll want to have no space between selectors. To achieve this, add an &
before the nested selector.
Ampersand Example:
.box {
background: red;
&.blue {
background: blue;
}
}
Compiled:
.box {
background: red;
}
.box.blue {
background: blue;
}
browser prefixes
Due to the rapidly evolving state of the web, some browsers implement features faster than others. Usually when a feature is implememnted before it makes it into the official CSS specification, browsers will allow a prefixed version of the property. The most common prefixes are: -webkit
, -ms
, -moz
, -o
. This can be a hge hastle to maintain. We highly recommend using an auto-prefixer to solve this issue. Google it.
@media Queries
In the new era of Responsive Web Design, things on the web should be built to work on a variety of screen sizes. The first tactic to accomplish this is to use percentage-based dimensions. Where the layout needs to adjust or elements need to change size, you should use @media Queries to introduce new styling.
Example:
.box {
// in a grid, two across
display: inline-block;
width: 50%;
@media (max-width: 600px) {
// at 600px or less, it becomes a list
display: block;
width: 100%;
}
}
Do not do this
Selecting IDs
IDs, when used properly, are unique and only used once. Targetting IDs, therefore, is inefficient and does not promote DRY code.
Lots of nesting in SCSS
Too much nesting in SCSS creates overly specific selectors, leading to poor performance and not reusable code.
!important
When CSS gets overly specific, it may be tempting to use !important
to get overrides to work, but DON’T DO IT. Use better selectors.
Selecting *
*
will select EVERYTHING. We only use it once, to define the box-model. In general, there are not many other reasons to select all and it can become very computationally intensive.
CSS Text Handling
font-family
EXAMPLE VALUES: Depends on your project.
To set what font gets used, use the font-family
property. In most of our projects this is done for you in our base css.
However, if you want to change what font is used, you should have numerous fallbacks like.
.my-class {
font-family: "Source Sans Pro", Verdana, Helvetica, Arial, sans-serif;
}
In this example Verdana will be used if the broswer does not have access to “Source Sans Pro”, then Helvetica, etc…
If you want to have them download a font, you’ll want to use @font-face
. Here’s a helpful resource TODO PROVIDE RESOURCE
font-size
EXAMPLE VALUES: 12px
, 1.2rem
, 1.4rem
, 1.6rem
font-size
controls how big the words will appear.
There are several units you can use, but we recommend pixels (px
) and root ems (rem
). Root ems are a percentage of the font size set on the html element.
As part of our code, we have a mixin that you should use in most cases. It will take care of both rems and a pixel fallback.
usage
.my-class {
@include font-size(1.6);
}
outputs
.my-class {
font-size: 16px;
font-size: 1.6rem;
}
color
EXAMPLE VALUES: $off-black
, #ffffff
, tint($mid-grey, 0.7)
, $red
, rgba(255, 255, 255, 0.5)
color
changes the color of the text.
In our code, we have variables corresponding to color values. SCSS Color Variables
line-height
EXAMPLE VALUES: 12px
, 30px
line-height
sets the vertical spacing between lines of text. We mostly use it to vertically center a single line of text. If there is a chance your text might wrap, use a different method as detailed by Centering in CSS: A Complete Guide, by CSS Tricks
For buttons, we commonly set the line-height to the height of the button to center the text vertically within the button.
.button {
height: 30px;
line-height: 30px;
}
text-align
EXAMPLE VALUES: center
, left
text-align
is fairly straightforward. It aligns text. text-align: center;
should mostly only be used for text that does not wrap. Center-aligned text that wraps is more difficult to read.
font-weight
EXAMPLE VALUES: normal
/400
, semibold
/600
, bold
/700
font-weight
tells the browser which cut of the given font you want to deliver to the browser. The numbers shown above generally correspond directly to the named weights beside them, though some font makers use different systems. These three are the most common values we use with Source Sans Pro.
font-style
EXAMPLE VALUES: normal
, italic
This attribute is basically used to set the text to italic. You only really need to set it to normal
if you’re overriding the italic
.
text-transform
EXAMPLE VALUES: normal
, uppercase
text-transform
will take the formatting of the given text and transform it to your defined value, most commonly to make something uppercase.
Uppercase text can be difficult to read, though, so we often pair this with font-weight
and letter-spacing
to help with that, as seen below.
<div class="name">Shaun Fox</div>
.name {
text-transform: uppercase;
font-weight: 600;
letter-spacing: 1px;
}
letter-spacing
EXAMPLE VALUES: 1px
, 1em
This is typically paired with text-transform
as demonstrated above. It should only ever be used on uppercase text. If used with lowercase text, readability is sacrificed.
text-decoration
EXAMPLE VALUES: none
, underline
text-decoration
is most often used to override the default browser styling of anchor tags. Frequently we’ll set the anchor to text-decoration: none
, which removes the underline, but we’ll give it other attributes that help define it as a link. For example:
.link {
text-decoration: none;
color: $blue;
&:hover {
border-bottom: 1px solid $blue;
}
}
white-space
EXAMPLE VALUES: nowrap
We primarily use white-space: nowrap
to force text to be one line, without wrapping. Most often used in conjunction with CSS truncation.
Checkboxes
<div class="checkbox-wrapper">
<input class="checkbox-input" type="checkbox" id="show_on_login" />
<label for="show_on_login">Show on login</label>
</div>
Dropdowns
We use the Bootstrap markup and JS for our dropdowns.
<div class="dropdown">
<button class="button dropdown-toggle" type="button" id="cool-dropdown" data-toggle="dropdown">
Dropdown
<svg viewBox="0 0 30 30" class="ico-arrow-down">
<use xlink:href="#ico-arrow-down"></use>
</svg>
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="cool-dropdown">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>
SCSS Color Variables
Our color variables, defined in _colors.scss
, are designed to help us reuse colors without having to remember hex values.
/* This is a default set of utility colors that we use from time to time. */
$red: #ed1c24;
$orange: #ff6600;
$yellow: #ffcc00;
$forest-green: #666600;
$green: #51b848;
$teal: #006666;
$blue: #0090cb;
$cyan: #00ccff;
$dark-cyan: darken($cyan, 10%);
$indigo: #2a1e5c;
$purple: #66439a;
$yellow-green: #efe80c;
$red-orange: #ff3600;
$tan: #F2F1E6;
$dark-tan: #C6C7C0;
/* These are all of our blacks, greys, and whites. */
$black: #000;
$off-black: #111;
$dark-grey: #666;
$mid-grey: #aaa;
$light-grey: #ccc;
$off-white: #eee;
$white: #fff;
/* Sometimes we'll define colors for very specific uses. They should get very specific names to help assure that they're only used in the appropriate place. */
$filter-background: #f9f4de;
$filter-active-button-color: #eee27e;
/* Our brand colors */
$snap-blue: #00a9ed;
$orange: #fe5019;
$midnight: #002B38;
/* If we find that we're recreating a particular color often, we should store it as a new variable, like this: */
$light-blue: tint($blue, 30%);
There are also a few functions we can use to transform colors to other colors.
Our custom color functions:
// Slightly lighten a color
@function tint($color, $percentage) {
@return mix($color, white, $percentage);
}
// Usage
.box {
background: tint($blue, 30); // mixes $blue at 30% and white at 70%
}
// Slightly darken a color
@function shade($color, $percentage) {
@return mix($color, black, $percentage);
}
// Usage
.button {
background: $blue;
border: 1px solid shade($blue, 80); // mixes $blue at 80% and black at 20%
}
These are our preferred way to transform colors because it outputs a slightly more predictable result than the standard lighten() and darken() built into SCSS.
Built-in SCSS color functions:
- Lighten:
background: lighten($blue, 20);
- Darken:
background: darken($orange, 60);
- RGBA:
color: rgba($off-black, 60);
- useful for letting text mix onto background colorsbackground: rgba($white, 95);
- useful for making the background of an element transparent without affecting the transparency of it’s contents.
There are many more color functions, but these are the main ones we use.
SCSS Mixins
Mixins are chunks of commonly used code that can be included again and again throughout your SCSS. Mixins can also take a variable when they’re called.
This snippet is used on parent elements with floating child elements to force them to wrap around their children.
@mixin clearfix {
&::after {
content: '';
display: table;
clear: both;
}
}
This snippet is used to generate REM-based font sizes with a PX backup. Note that it takes a variable ($size) and does some math with the value it’s given.
@mixin font-size($size){
font-size: ($size * 10) + px;
font-size: $size + rem;
}
More snippets that are used extensively:
// Uppercase, 600, letter-spaced
@mixin uppercase {
text-transform: uppercase;
font-weight: 600;
letter-spacing: 1px;
}
// Truncate text
@mixin truncate {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
// Vertical align anything
@mixin vertical-align {
display: block;
position: relative;
top: 50%;
transform: translateY(-50%);
transform-style: perserve-3d;
}
Usage
.box {
@include vertical-align();
@include uppercase();
@include font-size(1.8);
}
Outputs to:
.box {
display: block;
position: relative;
top: 50%;
transform: translateY(-50%);
transform-style: perserve-3d;
text-transform: uppercase;
font-weight: 600;
letter-spacing: 1px;
font-size: 18px;
font-size: 1.8rem;
}
SCSS Primer
Variables in SCSS
SCSS (or Sass) variables can be used for any kind of simple stored value. We most commonly use them for colors, but they can be used for lots of things.
$snap-blue: #00a9ed;
$orange: #fe5019;
$filter-buttons-height: 40px;
$global-padding: 2%;
Usage
.button {
background: $snap-blue;
height: $filter-buttons-height;
padding: 0 $global-padding;
}
This compiles to:
.button {
background: #00a9ed;
height: 40px;
padding: 0 2%;
}