Commits (367)
name: Frontend
full_name: Frontend Guild
mission: |
Provide cross-team support to both frontend developers and 18F team members seeking tips and best practices in the frontend space.
- url: 'https://drive.google.com/drive/#folders/0B84F26FpUP0lR1B2VVNGSi1MMVk/0B0C6PKlzps2JV3pqX3NJdm5WejA/0B5HeQa_YQ6-VTTlkVEFNZ2VWZEU'
text: Google Drive folder
- 18F/frontend-style-guide
- marco
- mhz
- marco
- mhz
- julia
owner_type: guild
enabled: true
space_before_bang: true
space_after_bang: false
enabled: false
convention: zero
enabled: true
severity: warning
enabled: true
enabled: true
enabled: true
enabled: false
enabled: true
enabled: true
style: same_line
enabled: true
ignore_single_line_blocks: true
enabled: true
enabled: true
present: true
enabled: false
style: short
enabled: true
style: lowercase
enabled: true
enabled: true
enabled: true
enabled: true
leading_underscore: false
filename_extension: false
enabled: true
allow_non_nested_indentation: false
character: space
width: 2
enabled: false
style: include_zero
enabled: true
force_nesting: true
enabled: true
allow_leading_underscore: true
convention: hyphenated_lowercase # or 'camel_case', or 'snake_case', or a regex pattern
enabled: true
max_depth: 4
severity: warning
enabled: false
enabled: true
include_nested: false
max_properties: 10
enabled: false
ignore_unspecified: false
severity: warning
separate_groups: false
enabled: true
extra_properties: []
enabled: true
allow_element_with_attribute: false
allow_element_with_class: false
allow_element_with_id: false
severity: warning
enabled: true
max_depth: 2
severity: warning
enabled: false # strict_BEM doesn't seem to be supported by Hound
convention: strict_BEM
enabled: true
allowed_shorthands: [1, 2]
severity: warning
enabled: true
allow_single_line_rule_sets: true
enabled: true
enabled: true
enabled: true
style: one_space
enabled: true
enabled: true
style: space
allow_single_line_padding: false
enabled: true
spaces: 0
enabled: true
style: single_quotes
enabled: true
enabled: false
enabled: true
enabled: true
enabled: true
enabled: true
enabled: false
properties: []
enabled: true
identifier_list: bourbon
include: []
exclude: []
enabled: true
severity: warning
enabled: false
## Building the guide locally
The Front-End Guide is built on the [USWDS Jekyll theme gem](https://github.com/18F/uswds-jekyll).
To run it locally, clone this repo and then:
1. Install [http://bundler.io/](Bundler) if you don't already have it: `gem install bundler`
1. Run `bundle install`.
1. Run `bundle exec jekyll serve`.
## Submitting a pull request
We welcome pull requests! Here's how to submit a PR:
1. The guide publishes the `master` branch, so make sure you have the latest version of it.
1. Create a new branch named in a way that describes your changes, optionally prefixed with your initials. Example: Heather Billings wants to create a PR that adds guidance around atomic CSS. She calls her branch `hjb-add-atomic-css`.
1. Push your branch and open a work-in-progress (WIP) PR as soon as you have commits, rather than waiting until you feel you are finished. **A WIP PR includes `[WIP]` in the title and contains a list of unfinished tasks.** WIP PRs allow for early feedback and help prevent wasted time. It also allows other guild members to pick up and work on pull requests that have been abandoned for whatever reason.
1. When your PR is ready for review, remove `[WIP]` from the title. This lets us know it's game time!
1. A PR must pass the automatic Federalist build check in order to be merged into master.
1. A PR must have one `approved` review in order to be merged into master. Any guild member with write access should be able to approve and merge PRs. (You cannot approve your own PR, sorry!)
## Submitting issues
Don't have time to file a pull request, but want to flag something? [Open an issue](https://github.com/18F/frontend/issues) stating what you think we should add or change and why, and we'll discuss it as a group.
## Public domain
This project is in the public domain within the United States, and
copyright and related rights in the work worldwide are waived through
the [CC0 1.0 Universal public domain dedication](https://creativecommons.org/publicdomain/zero/1.0/).
All contributions to this project will be released under the CC0
dedication. By submitting a pull request, you are agreeing to comply
with this waiver of copyright interest.
source 'https://rubygems.org'
gem 'uswds-jekyll', :git => 'https://github.com/18F/uswds-jekyll.git'
group :jekyll_plugins do
gem 'jekyll_pages_api_search'
gem 'jemoji'
remote: https://github.com/18F/uswds-jekyll.git
revision: 374e5c14940a71578d21d65186c05f507446a1c5
uswds-jekyll (3.0.0)
jekyll (~> 3.4)
remote: https://rubygems.org/
activesupport (4.2.10)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
colorator (1.1.0)
concurrent-ruby (1.1.5)
em-websocket (0.5.1)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
eventmachine (1.2.7)
ffi (1.11.1)
forwardable-extended (2.6.0)
gemoji (3.0.0)
html-pipeline (2.7.1)
activesupport (>= 2)
nokogiri (>= 1.4)
htmlentities (4.3.4)
http_parser.rb (0.6.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jekyll (3.8.6)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 0.7)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (~> 1.14)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-watch (2.2.1)
listen (~> 3.0)
jekyll_pages_api (0.1.6)
htmlentities (~> 4.3)
jekyll (>= 2.0, < 4.0)
jekyll_pages_api_search (0.5.0)
jekyll_pages_api (~> 0.1.4)
sass (~> 3.4)
jemoji (0.9.0)
activesupport (~> 4.0, >= 4.2.9)
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (~> 3.0)
kramdown (1.17.0)
liquid (4.0.3)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
mercenary (0.3.6)
mini_portile2 (2.4.0)
minitest (5.11.3)
nokogiri (1.10.4)
mini_portile2 (~> 2.4.0)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (4.0.1)
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
rouge (3.10.0)
ruby_dep (1.5.0)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
thread_safe (0.3.6)
tzinfo (1.2.5)
thread_safe (~> 0.1)
As a work of the United States Government, this project is in the
public domain within the United States.
Additionally, we waive copyright and related rights in the work
worldwide through the CC0 1.0 Universal public domain dedication.
## CC0 1.0 Universal Summary
This is a human-readable summary of the
[Legal Code (read the full text)](https://creativecommons.org/publicdomain/zero/1.0/legalcode).
### No Copyright
The person who associated a work with this deed has dedicated the work to
the public domain by waiving all of his or her rights to the work worldwide
under copyright law, including all related and neighboring rights, to the
extent allowed by law.
You can copy, modify, distribute and perform the work, even for commercial
purposes, all without asking permission.
### Other Information
In no way are the patent or trademark rights of any person affected by CC0,
nor are the rights that other persons may have in the work or in how the
work is used, such as publicity or privacy rights.
Unless expressly stated otherwise, the person who associated a work with
this deed makes no warranties about the work, and disclaims liability for
all uses of the work, to the fullest extent permitted by applicable law.
When using or citing the work, you should not imply endorsement by the
author or the affirmer.
## Front-End Guild
18F promotes team best practices across specialty areas through guilds. These guilds support their members in whatever way deemed most appropriate by those members themselves.
This repo is where the 18F Front-End Guild keeps its guide to best practices and resources for front-end development.
### Quicklinks
- Guide: https://frontend.18f.gov/
- [CONTRIBUTING.md](CONTRIBUTING.md) on how to build this guide locally and submitting PRs/issues.
## Our mission
We believe that government websites should be functional, maintainable, and thoughtfully designed. Our guild helps TTS promote the adoption and advancement of front-end design and development best practices. In this way, TTS can lead by example while providing effective services that help our partners and customers fulfill their missions.
To achieve our vision, the Front-End Guild works to:
- Support the continuous learning necessary for successful front-end work.
- Provide TTS developers with easy-to-understand, actionable guidance around front-end best practices.
- Promote a central knowledge base of shared tools and common patterns.
- Create a healthy and supportive internal environment so that we can, in turn, bolster healthy external communities related to our work.
## How to track what we're doing, and how you can be involved!
We use issues in this repo to track work. If you'd like to suggest a new topic or flag an issue, please [file an issue](https://github.com/18F/frontend/issues/new/).
The front-end space is rapidly changing, and our guide is a living document. Please suggest edits or changes via pull request.
title: 18F Front-End Guide
- /assets/css/styles.css
- Gemfile
- Gemfile.lock
- go
theme: uswds-jekyll
- scope:
path: ""
type: "pages"
layout: page
permalink: pretty
markdown: kramdown
style: compressed
# Author/Organization info to be displayed in the templates
name: 18F
url: https://18f.gsa.gov
# Point the logo URL at a file in your repo or hosted elsewhere by your organization
logourl: /assets/img/18f-logo.png
logoalt: 18F logo
google_analytics_ua: UA-48605964-19
name: Front-End Guide
description: Main repository
url: https://github.com/18F/frontend
url: "https://guides.18f.gov/"
text: Read more 18F Guides
- rel: shortcut icon
type: image/ico
href: /assets/uswds/img/favicons/favicon.ico
- rel: icon
type: image/png
href: /assets/uswds/img/favicons/favicon.png
- rel: icon
type: image/png
sizes: 192x192
href: /assets/uswds/img/favicons/favicon-192.png
- rel: apple-touch-icon-precomposed
href: /assets/uswds/img/favicons/favicon-57.png
- rel: apple-touch-icon-precomposed
sizes: 72x72
href: /assets/uswds/img/favicons/favicon-72.png
- rel: apple-touch-icon-precomposed
sizes: 114x114
href: /assets/uswds/img/favicons/favicon-114.png
- rel: apple-touch-icon-precomposed
sizes: 144x144
href: /assets/uswds/img/favicons/favicon-144.png
# This is the configuration for the site footer.
# Configuration for type of footer.
# Footer types can be only be medium at the moment
type: medium
# Configuration for "Return to top" link.
# Customize with 'text' and 'href' properties.
# Comment out to the following section to hide.
text: Return to top
href: '#'
# Configuration for "Edit this page" link in the footer.
# Customize with 'text' property.
# Uncomment the following line to show.
# edit_page:
# text: Edit this page
# Configuration for "Last updated" date and time.
# Uncomment the following line to show.
# last_updated: true
# Configuration for which links show at the top of the footer.
# this is a key into _data/navigation.yml
# Configuration for footer heading. (optional)
# Configuration for agency logo(s) (shown side by side).
# If the logo is external add external: true
- src: /assets/images/18f-Logo.svg
alt: 18F
# Configuration for footer contact links
# Configuration for social media links
# Comment out links you don't want to use (RSS is an example)
# - text: Facebook
# href: https://facebook.com
# external: true
# type: facebook
# - text: Twitter
# href: https://twitter.com
# external: true
# type: twitter
# - text: YouTube
# href: https://youtube.com
# external: true
# type: youtube
# - text: RSS Feed
# href: https://usa.gov/
# external: true
# type: rss
# Configuration for contact links for email, phone, etc...
# - text: (800) CALL-GOVT
# href: tel:1-800-555-5555
# - text: info@agency.gov
# href: mailto:info@agency.gov
# This is the configuration for the site header.
# Uncomment this statement (by removing the leading '# ') to set the
# header title differently from the site's title (as defined in
# _config.yml).
# title: Header title
usa_banner: true
# this is a key into _data/navigation.yml
links: primary
# this is a key into _data/navigation.yml
links: secondary
# to enable search, change this to an object with 'action' and
# 'param' keys, e.g.
# search:
# action: /search/
# query: q
# _data/navigation.yml
- text: CSS
href: /css/
- text: JavaScript
href: /javascript/
- text: Web Components
href: /web-components/
- text: Security
href: /security/
- text: More 18F guides
href: https://guides.18f.gov/
external: true
- text: Architecture
href: /css/architecture/
- text: Documentation
href: /css/documentation/
- text: Frameworks
href: /css/frameworks/
- text: Formatting
href: /css/formatting/
- text: Inheritance
href: /css/inheritance/
- text: Linting
href: /css/linting/
- text: Naming
href: /css/naming/
- text: Preprocessors
href: /css/preprocessors/
- text: Specificity
href: /css/specificity/
- text: Units
href: /css/units/
- text: Variables
href: /css/variables/
- text: Dependencies
href: /javascript/dependencies/
- text: Frameworks
href: /javascript/frameworks/
- text: Libraries
href: /javascript/libraries/
- text: Style / Linting
href: /javascript/style/
- text: Content Security Policy (CSP)
href: /security/content-security-policy/
{% if footer %}
<footer class="usa-footer usa-footer-medium" role="contentinfo">
{% if footer.last_updated %}
<div class="usa-grid">
<div class="usa-width-one-whole">
<p>Last updated: {{ page.last_modified_at | date: '%B %d, %Y at %I:%M %p' }}</p>
{% endif %}
{% if footer.top %}
<div class="usa-grid usa-footer-return-to-top">
<a href="{{ footer.top.href | default: '#' }}">{{ footer.top.text | default: 'Return to top' }}</a>
{% endif %}
{% if footer.links %}
{% assign footer_links = site.data.navigation[footer.links] | default: footer.links %}
{% assign _sizes = 'whole half third fourth sixth' | split: ' ' %}
{% assign _size = footer_links.size | minus: 1 %}
{% assign _size = _sizes[_size] | default: 'whole' %}
<div class="usa-footer-primary-section">
<div class="usa-grid">
<nav class="usa-footer-nav">
<ul class="usa-unstyled-list">
{% for _link in footer_links %}
<li class="usa-width-one-{{ _size }} usa-footer-primary-content">
<a class="usa-footer-primary-link" href="{% if _link.external == true %}{{ _link.href }}{% else %}{{ _link.href | relative_url }}{% endif %}">
{{ _link.text }}
{% endfor %}
{% endif %}
{% if footer.logos or footer.heading or footer.contact %}
<div class="usa-footer-secondary_section">
<div class="usa-grid">
<div class="usa-footer-logo usa-width-one-half">
{% if footer.logos %}
{% for logo in footer.logos -%}
{% if logo.url %}
<a href="{{ logo.url }}">
{% endif %}
<img class="usa-footer-logo-img" src="{% if logo.external %}{{ logo.src }}{% else %}{{ logo.src | relative_url }}{% endif %}" alt="{{ logo.alt }}"{% if logo.width %}width="{{ logo.width }}"{% endif %}{% if logo.height %}height="{{ logo.height }}"{% endif %}>
{% if logo.url %}
{% endif %}
{% endfor %}
{% endif %}
{% if footer.heading %}
<h3 class="usa-footer-logo-heading">{{ footer.heading }}</h3>
{% endif %}
<div class="usa-footer-contact-links usa-width-one-half">
<ul class="usa-unstyled-list">
<li><a href="https://github.com/18F/uswds-jekyll">18F USWDS-Jekyll theme</a></li>
<li>Hosted by <a href="https://federalist.18f.gov/">Federalist</a></li>
<li>Maintained by <a href="https://18f.gsa.gov/">18F</a></li>
{% endif %}
{% endif %}
pre {
background-color: #f1f1f1;
font-size: 1.5rem;
padding: 1rem;
.usa-footer-contact-links {
padding: 2rem 0;
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Black_w_x2F_white_type" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 333 333" enable-background="new 0 0 333 333" xml:space="preserve">
<path d="M327.3,0H5.7C2.5,0,0,2.5,0,5.7v321.6c0,3.1,2.5,5.7,5.7,5.7h321.6c3.1,0,5.7-2.5,5.7-5.7V5.7C333,2.5,330.5,0,327.3,0z"/>
<path fill="#FFFFFF" d="M98,229.3c0,1.1-0.9,2-2,2H83.5c-1.1,0-2-0.9-2-2V117.4H65.2c-1.1,0-2-0.9-2-2v-11.9c0-1.1,0.9-2,2-2h30.8
<path fill="#FFFFFF" d="M269.8,115.4c0,1.1-0.9,2-2,2h-34.4v39h28.3c1.1,0,2,0.9,2,2v11.9c0,1.1-0.9,2-2,2h-28.3v57.1
<path fill="#FFFFFF" d="M157.5,233.4c-21.9,0-39.8-17.9-39.8-39.8c0-13.2,6.4-25.1,17.1-32.5c-7.7-6.6-12.3-16.3-12.3-26.4
C197.3,215.5,179.4,233.4,157.5,233.4z M157.5,169.6c-13.2,0-23.9,10.7-23.9,23.9c0,13.2,10.7,23.9,23.9,23.9
c13.2,0,23.9-10.7,23.9-23.9C181.4,180.4,170.7,169.6,157.5,169.6z M157.5,153.8c10.6,0,19.1-8.6,19.1-19.1
#! /bin/bash
usage() {
echo "Usage: $0 [path to target repository]"
exit 1
if [ $# -ne 1 ]; then
echo "Error: Exactly one target repository must be specified"
if [ ! -d $1 ]; then
echo "Error: $1 is not a directory"
# Hack per:
# http://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself
pushd $(dirname $0) >/dev/null
popd >/dev/null
TARGET=$(echo "$1/" | sed 's#//$#/#')
rsync -av --exclude .DS_Store $TEMPLATE_ROOT/{_includes,_layouts,assets} $TARGET
#! /usr/bin/env ruby
require 'English'
Dir.chdir File.dirname(__FILE__)
def try_command_and_restart(command)
exit $CHILD_STATUS.exitstatus unless system command
exec({ 'RUBYOPT' => nil }, RbConfig.ruby, *[$PROGRAM_NAME].concat(ARGV))
require 'bundler/setup' if File.exist? 'Gemfile'
rescue LoadError
try_command_and_restart 'gem install bundler'
rescue SystemExit
try_command_and_restart 'bundle install'
require 'go_script'
rescue LoadError
try_command_and_restart 'gem install go_script' unless File.exist? 'Gemfile'
abort "Please add \"gem 'go_script'\" to your Gemfile"
require 'guides_style_18f'
extend GoScript
check_ruby_version '2.1.5'
command_group :dev, 'Development commands'
def_command :update_nav, 'Update the \'navigation:\' data in _config.yml' do
GuidesStyle18F.update_navigation_configuration Dir.pwd
def_command :update_theme, 'Update the guides_style_18f gem' do
def_command :update_gems, 'Update Ruby gems' do |gems|
update_gems gems
def_command :serve, 'Serve the site at localhost:4000' do
def_command :build, 'Build the site' do
execute_command ARGV
install: --no-ri --no-rdoc
update: --no-ri --no-rdoc
\ No newline at end of file
title: Architecture
permalink: /css/architecture/
sidenav: css
# Architecture
A site's architecture should be based on its goals and purposes. This means the
guidance here should be adapted to different sites and situations.
## Modular or component architecture
When using a modular or component architecture, every page is broken into a
series of modular components. There are two sets of these components:
`components` and `modules`. The architecture starts out with basic HTML element
rules: HTML, p, a, form, etc tags that than have components and modules written
on top of them. Components are very basic structure such as buttons, blurbs,
navs, and positioning structures like insets, island, and enclosure. From
here, modules are built with these components. This architecture also attempts
to keep the specificity trend in an upwards curve as you move down in the file
(more on this to come).
- Start with an elements file for all tag rules (a, h1-h5, p, \*, html, body).
- Create component files for each structural element, such as buttons, navs,
etc. These are mainly class-based and use [BEM] or another [naming
- Create more specific structure with modules. For instance, if the logo image
and text needs very specific treatment, use a module.
- Build modules from components through mixins, extends, and HTML.
- Modules can have higher specificity, it’s fine to use deeper nesting.
- Have an overrides file or folder comprised of global rules that are meant to
override components and modules.
- These can be generic utilities.
- A good thing to put here are breakpoint-specific rules, such as hiding
something at small breakpoints.
### File structure
For the `util`, `typography`, `elements`, and `overrides` files, once they grow
too large (300 lines or more) in size, split them into their own folder with
sub files.
## Importing
As you likely know, CSS rules that are later in the file override earlier
rules. This means Sass imports can be used to control inheritance and
- Start with base elements.
- Move to single nested classes and utils.
- Move next to more specific classes, often with nesting.
- Move next to overrides, possibly with !important rules.
- Import alphabetically.
- Only modify import order for groups of files, not specific files.
// Bad
@import 'module/logo';
@import 'component/mask';
@import 'component/button'; /* Has to be imported after "mask" */
// Good
@import 'component/button';
@import 'component/mask';
@import 'module/logo';
[BEM]: http://getbem.com/introduction/
title: CSS
permalink: /css/
sidenav: css
The purpose of the CSS coding styleguide is to create consistent CSS or
preprocessor CSS code across 18F. The styleguide should be treated as a guide
&mdash; rules can be modified according to project needs.
title: Documentation
permalink: /css/documentation/
sidenav: css
# Documentation
## Sass Comments
Be intentional when you use `//` (silent comments) versus `/* */`
(which are preserved in the CSS output). When in doubt, use `//`.
## KSS
Use KSS for documentation. More information on KSS can be found on the
[official site](http://warpspire.com/kss/).
### Example
// Button
// Various buttons on the site.
// Markup
// <a class="button {{ modifier_class }}">
// <span class="button__text">Link</span
// </a>
// .button-modified - A button with a different style.
// Styleguide component.button
.button {
.button-modified {
### Rationale
KSS is the most common CSS documentation method to date. While it’s not perfect,
the generated documentation can be modified through templates.
title: Formatting
permalink: /css/formatting/
sidenav: css
# Formatting
We recommend using [Prettier](https://prettier.io), and enabling it in your
editor by default. Prettier is an automatic code formatter that will make your
code format consistent. This way we don't have to argue over how to format our
code - we just let the tools enforce something! Prettier works with both plain
Do not use shorthand declarations unless you need to explicitly set all the
available values.
// Bad
margin: inherit 3em;
// Good
margin-bottom: 3em;
margin-top: 3em;
margin: 3em 4em 2em 1em;
Avoid arbitrary numbers that are repeated, or linked, or dependent on other
parts of the code, (aka “magic numbers”).
// Bad
.component {
top: 0.327em;
// Better
* 1. Magic number. This value is the lowest I could find to align the top of
* `.foo` with its parent. Ideally, we should fix it properly.
.component {
top: 0.327em;
// Good
$align_top: 100%;
.component {
top: $align_top;
## Order
- Use the following ordering:
1. variables
2. @extend directives
3. @include directives
4. declaration list (`property: name;`)
5. media queries
6. pseudo-states (`:checked`, `:target`, etc.) and pseudo-elements
(`::after`, `::selection`, etc.)
7. nested elements
8. nested classes
- Use alphabetical order or type order for declarations. Pick one to keep the
whole project consistent.
- Place a new line before nested selectors unless they are after the first
- Treat nested includes, such as Neat's media includes –
`@include media($small-screen)` — as a standard media query, rather than a
Sass @include. So they would be sorted directly after the declaration list.
- Place mixin calls with `@content` after nested selectors.
- You may deviate the sorting order to better suit your project's needs, as
long as it's consistent throughout the project.
// Bad
.module {
.module-element {
color: #fff932;
// Good
.module {
.module-element {
color: #fff932;
// Good
.module {
$amount = 3;
@extend .component;
@include sizing($amount);
margin-top: $amount * 1em;
text-align: center;
@include media($small-screen) {
margin-top: ($amount + 10em);
&::before {
content: "hello";
.module__ele {
color: #fff932;
title: Frameworks
permalink: /css/frameworks/
sidenav: css
# Frameworks
18F currently recommends using the [U.S. Web Design System](https://github.com/uswds/uswds) as it is specifically designed to help build fast, accessible, mobile-friendly federal government websites.
Sometimes, projects utilize other CSS frameworks such as:
1. [Bourbon](https://www.bourbon.io/)
2. [BassCSS](https://www.basscss.com/)
These frameworks were chosen because they're relatively unopinionated about
design decisions while still providing the helpers that make frameworks
essential to fast and accurate frontend work, for example, solutions for
responsive design, grids, and common design patterns. In addition, both
frameworks, through modular design and excellent documentation, make it easy
for the designer or developer to only use the parts that they need, rather than
including a hefty library.
## Do not use Bootstrap
18F specifically does not recommend using [Bootstrap](http://getbootstrap.com/) for production work
because it can be difficult to adapt its opinionated styles to bespoke design work.
title: Inheritance
permalink: /css/inheritance/
sidenav: css
# Inheritance
## Mixins
- Use mixins for groups of properties that appear together intentionally and
are used multiple times.
@mixin clearfix {
&:after {
content: '';
display: table;
clear: both;
- Use mixins for components to change size.
- Use mixins when something requires parameters.
@mixin size($width, $height: $width) {
width: $width;
height: $height;
- Do not use mixins for browser prefixes. Use [Autoprefixer](https://github.com/postcss/autoprefixer).
// Bad
@mixin transform($value) {
-webkit-transform: $value;
-moz-transform: $value;
transform: $value;
## Extend
Be very careful with using `@extend`. It's a powerful tool that can have
disastrous side-effects. Before using please consider:
- Where is my current selector going to be appended?
- Am I likely to be causing undesired side-effects?
- How large is the CSS generated by this single extend?
If you're unsure of using `@extend`, follow these rules to avoid running into
- Use `@extend` from within a module, not across different modules.
- Use `@extend` on [placeholders] exclusively, not on actual selectors.
- Make sure the placeholder you extend is present as little as possible in the
You can use [mixins] in place of selectors. While mixins will copy more code,
the difference will often be negligible once the output file has been gzipped.
[mixins]: http://sass-lang.com/guide#mixins
[placeholders]: http://thesassway.com/intermediate/understanding-placeholder-selectors
title: Linting
permalink: /css/linting/
sidenav: css
# Linting
The styleguide provides a method of linting [Sass] code to ensure it conforms
to the rules in the styleguide. This linting tool will go through all Sass code
and issue warnings wherever the code differs from the styleguide. We've created
a specific [`.scss-lint.yml` file][scss-lint yaml] that's configured to work
with the css coding styleguide. There are three ways to setup linting:
* on GitHub with Hound
* locally with ruby
* locally with node
## On GitHub with Hound
1. Go to [Hound](https://houndci.com/).
2. Sign in with GitHub.
3. Activate the respository through [Hound](https://houndci.com/repos).
4. Add the [`.scss-lint.yml` file][scss-lint yaml] to the base of your
## Locally with ruby
1. Add the [`.scss-lint.yml` file][scss-lint yaml] to the base of your
2. Install the [scss-lint] gem with `gem install scss_lint`
3. Run scss-lint: `scss-lint app/assets/stylesheets/`
## Locally with node (experimental!)
1. Run `npm install --save-dev @18f/stylelint-rules` to download the package and save it to your package.json
2. The package provides both a gulp task and a cli interface. Detailed usage instructions can be found in the [README](https://github.com/18F/stylelint-rules)
## Shortcomings
### scss-lint
The scss-lint tool currently lacks the functionality to check these rules in
the CSS coding styleguide:
- Does not limit line width to 80 characters
- Does not check for numeric calculations in parentheses
- Does not sort properties in quite the order we want (defaults to
### stylelint
This tool is still being evaluated, so not every rule in our current styleguide
is supported by stylelint. scss-lint is purpose built for SCSS and is therefore
a bit more feature rich. The following rules are currently not supported:
- PropertySpelling
- UnecessaryParentReference
That being said, if you want to avoid a dependency on ruby in your project and
still benefit from reliable SCSS linting, please test out this tool!
[Sass]: http://sass-lang.com/
[scss-lint]: https://github.com/brigade/scss-lint
[scss-lint yaml]: https://raw.githubusercontent.com/18F/frontend/18f-pages-staging/.scss-lint.yml
[stylelint-rules]: https://github.com/18F/stylelint-rules
title: Naming
permalink: /css/naming/
sidenav: css
# Naming
- HTML elements should be in lowercase.
div {
- Classes should be lowercase.
- Avoid camelcase.
- Name things clearly.
- Write classes semantically. Name its function not its appearance.
// Bad
// Avoid uppercase
.ClassNAME { }
// Avoid camel case
.commentForm { }
// What is a c1-xr? Use a more explicit name.
.c1-xr { }
- Avoid presentation- or location-specific words in names, as this will cause
problems when you (invariably) need to change the color, width, or feature
// Bad
// Good
- Be wary of naming components based on content, as this limits the use of the
// Danger zone
// Better
- Don't abbreviate unless it’s a well-known abbreviation.
// Bad
// Good
- Use quotes in type pseudo selectors.
// Good
.top_image[type="text"] {
- Name CSS components and modules with singular nouns.
.button {
- Name modifiers and state-based rules with adjectives.
.is_hovered {
- If your CSS has to interface with other CSS libraries, consider namespacing
every class.
## Naming Methodologies
When it comes to naming, the most important thing is consistency. The
recommended way to do this is using an existing methodology like [BEM](#BEM),
or use a custom one that’s clearly defined.
### BEM
[BEM][BEM] (**B**lock, **E**lement, **M**odifier) structures CSS such that
every entity is composed of (you guessed it) blocks, elements and modifiers.
From [Harry Roberts][mindbemding]:
> The point of BEM is to tell other developers more about what a piece of
> markup is doing from its name alone. By reading some HTML with some classes
> in, you can see how – if at all – the chunks are related; something might
> just be a component, something might be a child, or element, of that
> component, and something might be a variation or modifier of that component.
18F generally recommends using a modified BEM methodology outlined in the next
subsection. However, you might want to use standard BEM when:
* You need a naming scheme that general CSS developers will already be familiar
with or an existing naming scheme hasn’t been consistent enough.
* When you want to use JavaScript to modify the BEM class names dynamically.
Here is an example of BEM in SCSS:
// block
.inset {
margin-left: 15%;
// element
.inset__content {
padding: 3em;
// modifier
.inset--sm {
margin-left: 10%;
.inset__content {
padding: 1em;
// modifier
.inset--lg {
margin-left: 20%;
### Suggested custom methodology
The 18F recommendation for a naming methodology is a modified version of BEM.
It still uses blocks, sections within blocks and modifiers, but with an
abbreviated syntax.
### Naming methodology resources
- [article explaining BEM][mindbemding]
- [BEM website][BEM]
## js- flagged classes
Don't attach styles to classes with a `js-` flag. These classes are reserved for javascript.
// Bad
.js-people {
color: #ff0;
### Rationale
A `js-` flagged class needs to be highly portable. Adding styles to it breaks that portability.
## test- flagged classes
Don't attach styles to classes with a `test-` flag. These classes are reserved for testing hooks such as those used by selenium.
// Bad
.test-people {
color: #ff0;
[BEM]: https://en.bem.info/method/
[mindbemding]: http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/
title: Preprocessors
permalink: /css/preprocessors/
sidenav: css
# Preprocessors
The most supported CSS preprocessor at 18F is [Sass](http://sass-lang.com/)
(SCSS). Using this pre-processor means you'll get supported resources such as
frameworks, libraries, tutorials, and a comprehensive styleguide as support.
In addition, 18F uses a [`.scss-lint.yml`
to keep our CSS code compliant with our own styleguide.
_That being said, any preprocessor is allowed as long as it's a sound project
and has community support._
The recommended way to compile your Sass code is through
[node-sass](https://www.npmjs.com/package/node-sass), rather than Ruby Sass.
This allows eliminating the Ruby dependency for projects that don't already
require it and is the fastest method of compiling Sass.
title: Specificity
permalink: /css/specificity/
sidenav: css
# Specificity
- IDs should be reserved for JavaScript. Don’t use IDs for styles.
// Bad
#component { }
// Good
.component { }
- Don't nest more than 3 layers deep.
- Do not fix problems with ```!important```. Use ```!important``` purposefully.
// Bad
.component {
width: 37.4% !important;
// Good
.hidden {
display: none !important
- Keep specificity low and trend upwards in specificity as you move further
down file. See the [specificity graph](#specificity-graph) section for more
- Don't use unnecessary tag selectors.
// Bad
p.body_text { }
// Good
- If you have to hack specificity, use a safe hack: the _multi class_.
// multi-class hack
.component.component { }
## Specificity graph
An easy rule to use when dealing with specificity is to start from a low
specificity and curve to higher specificity as you move towards the bottom of
the output file. Since CSS rules get replaced by rules further down in the
file, you'll override rules in an expected way.
There’s a tool that can graph your files’ specificity, [CSS specificity
graph](http://jonassebastianohlsson.com/specificity-graph/). Run your final
output file through this tool and strive for a curve trending upwards.
### Resources
* [CSS specificity graph](http://jonassebastianohlsson.com/specificity-graph/)
* [Explanation](http://csswizardry.com/2014/10/the-specificity-graph/)
## Rationale
With specificity comes great responsibility. Broad selectors allow us to be
efficient, yet can have adverse consequences if not tested. Location-specific
selectors can save us time, but will quickly lead to a cluttered stylesheet.
Exercise your best judgement to create selectors that find the right balance
between contributing to the overall style and layout of the DOM.
* When modifying an existing element for a specific use, try to use specific
class names. Instead of `.listings-layout.bigger` use rules like
`.listings-layout.listings-bigger`. Think about ack/grepping your code in the
* Use lowercase and separate words with hyphens when naming selectors. Avoid
camelcase and underscores. Use human-readable selectors that describe what
element(s) they style.
* Attribute selectors should use double quotes around values. Refrain from
using over-qualified selectors; `div.container` can simply be stated as
* IDs should be reserved for JavaScript. Unless you have a very good reason,
all CSS should be attached to classes rather than IDs. When in doubt, use a
class name. This prevents target confusion and allows CSS devs and JS devs to
co-exist in the same code in peace. If you must use an id selector (`#id`)
make sure that you have no more than one in your rule declaration.
title: Units
permalink: /css/units/
sidenav: css
# Units
## Measurements
- Use **rem** units for font sizes with a px fallback. This can be done with
the following mixin:
@mixin font-size($sizeValue: 1.6) {
font-size: ($sizeValue * 10) + px;
font-size: $sizeValue + rem;
- Set the HTML font size to `10px` to ensure that `0.1rem` equals `1px`.
html {
font-size: 10px;
- Use **em** units for positioning.
- Use **percentages** when layout components stay relational to each other
(e.g. a main content area that takes up 75% of the screen and a sidebar that
takes up 25%).
// Good
.panel-a {
width: 25%;
.panel-b {
width: 75%;