BarkleyREI Front End Coding Standards


Introduction

[#] [Edit on Github]

This document contains the guidelines and best practices for the front-end web development team at BarkleyREI.

Each item here represents either:

  • A reminder to follow existing standards or industry conventions.
  • Guidance on what constitutes professional patterns and organization.
  • A decision we've made favoring one method over its alternatives.

What this document is not is a series of explanations as to how front-end technologies work; a basic familiarity is assumed. It also does not provide evaluations of the pros and cons of various alternatives unless there is common confusion about which option is best; when appropriate we pick what we consider to be the best solutions and present them. Issues that don't yet have a clear solution are considered flexible and may or may not be listed.

Goals

[#] [Edit on Github]

Our motivations in creating this document are to:

  1. Foster code consistency across our projects.
  2. Facilitate ease of maintenance.
  3. Ensure we create professional quality websites.
  4. Guide staff on-boarding or educate new developers.

This document is not intended to replace common sense, conventions requested by particular clients, teams, or prevent expressive or creative solutions to problems. Team or project-specific agreements or client requests will always supersede this document's content.

Deliverables

[#] [Edit on Github]

Quality deliverables are essential for professionals. Sloppy or messy deliverables are unprofessional and reflect poorly on the final product and the delivery team. Please remove legacy files, be certain the work is delivered in a clean file system, and in an orderly, logical structure that serves a clear purpose.

Unless specifically requested, delivery of code should be a zip of the compiled static assets. If the client desires a part of the unbuilt project or the entire project itself, documentation should be prepared for the client accordingly, and minimal support offered. If a client does receive the code base for a project, they must be made aware that any changes made on their end are separated from our final version of the code and will be the sole responsibility of the client.

The deployment of a project may be satisfied by the integration of the template into their CMS or hosted server.

There is no official standard of project documentation at BarkleyREI yet, but as much documentation as is possible should be provided along with finished code.


Professional Responsibility

[#] [Edit on Github]

We are experts in our field creating solutions for our clients and their audiences, not for ourselves. Every technology and code choice needs to be measured against the benefits to the project versus the cool factor or how trendy a particular solution may be.

Our industry is wrought with the flavor of the month, so please be deliberate.

Always remember that just because you can does not mean you should. Some solutions are not reliable, may not perform well, or may be difficult to maintain over time or add more code to. Always remember your code may not be the last added to a project in that particular feature area.

Getting Started

[#] [Edit on Github]

At the outset of the project it is essential to properly understand the goals of the project and identify the specific deliverables expected of the front-end team. Where your responsibilities begin and end should not be taken for granted or assumed.

It's important to understand how the development environment will work, what tools will be available, and what the differences between development, test, and production environments may ultimately be.

Finally, all project teams should get a reasonable understanding of the what client's browser and device requirements are. Make no assumptions as to the technology available either from the client or their audience.

BarkleyREI has testing and coding standards documents that outline the base deliverable requirements of our code. These are delivered to the client during the discovery phase, and any special requirements the client has is recorded to those documents and signed for approval.

Pillars of Front-end Development

[#] [Edit on Github]

Whenever possible, the front-end technology solutions produced shall adhere to industry best practices honoring as strict a separation of concerns as possible between:

  • Semantic HyperText Markup Language (HTML) for structure
  • Cascading Style Sheets (CSS) for presentation
  • JavaScript (JS) for behavior and interaction

When at all possible, we strive for a progressive enhancement strategy.

General Standards

[#] [Edit on Github]

For any project:

  • Consistency and conventions between team members is paramount.
  • Solutions should be as simple and clear as possible.
  • Solutions should serve a specific purpose.
  • Clever code does not mean good code; readability is critical.
  • Complex code solutions should be documented via comments, and if possible, documented elsewhere in a deliverable format (PDF, DOCX, etc).

A key hallmark of professional code includes a notion that while we are writing code, we must reach a desired goal, and we must also create code that can be read and understood by others.

Code Consistency

[#] [Edit on Github]

Usage of the same patterns is critical between team members so as to never cause confusion.

It's worth establishing conventions at the project start or enabling automatic settings in the build or editor environments that might enforce particular rules.

Indentation

[#] [Edit on Github]

Please consistently indent, nest, include braces, quotes, and newlines so that code is clear and can be read easily. New code that is added should never deviate from existing formatting conventions or change the indent levels.

For all code languages, we require the use of hard tabs at all times.

You may modify your editor-of-choice to display tabs as 4 spaces, but they should exist as tabs to maintain consistency.

Readability

[#] [Edit on Github]

We encourage liberal use of whitespace, comments, and descriptive variable names as appropriate for writing easy-to-read code.

There is no need to write code in an obfuscated or compressed way for the purpose of file-size savings.

We will use build processes to optimize files; this includes concatenating files, code minification, gzipping, and setting "Far Future Expires".

The ability for another developer to read the code is paramount above other concerns, especially if optimization can be handled another way.

Third-Party Libraries

[#] [Edit on Github]

Un-minified libraries and third-party scripts should be leveraged in local development environments for easier debugging if available. The code should not be committed to source control directly, but instead referenced in the Assemble files so that they are included in compiled versions of JavaScript deliverables. The final products will be compressed and minified with the rest of the source for delivery. Use bower to reference as much as possible before storing any third party scripts directly in the project. Make sure to use --save-dev to add the library to your bower config.

Likewise, third-party code and libraries should never be modified and their original source and the license must be documented and be appropriate for a project. Any changes to third party code must be agreed upon and must be for specific reasons. If changes are mandated by bug fixes then the appropriate upstream project should have the changes submitted (assuming the code is part of an open source repository).

If a vendor library needs to be customized for the specific project, or is not generally available to install via bower, it can be saved in the /app/js/vendor directory of the project. The bower_components directory is not (and should not be) versioned and thus any changes made in that environment will not be saved.

<!-- build:js js/main.js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/foundation-sites/js/foundation.core.js"></script>
<script src="bower_components/foundation-sites/js/foundation.util.triggers.js"></script>
<script src="bower_components/foundation-sites/js/foundation.util.mediaQuery.js"></script>
<script src="bower_components/foundation-sites/js/foundation.sticky.js"></script>
<script src="js/vendor/prism.js"></script>
<script src="js/standards.js"></script>
<!-- endbuild -->

Library code should be treated as an external dependency and should be considered something that may need to be wholesale updated or replaced at a later time.

Inclusion of any third-party code should be carefully considered and verified with the project team as the appropriate solution to a given problem. "Adding another plug-in" is not always the best solution. Finally, selection of third party libraries should be done carefully and not be out of alignment with the nature of the problem being addressed.

To be blunt, use the right tool for the right job.

HTML

[#] [Edit on Github]

HTML markup defines the content of a document and gives it a rudimentary structure such as section dividers, headers, paragraphs, lists, menus, and forms.

Goals for Markup

[#] [Edit on Github]

Please follow conventions established for a given project so all team members can have the same expectations around document structure and markup.

Structural consistency is critical when talking about the types of pages being used on a site or in a Web app. The markup structure provides all the necessary hooks for scripting and behavior, so it's important that the appropriate hooks are in place.

A clear, clean, and concise HTML structure is also necessary for semantics, flexibility, and a reliable deployment environment. Do not deviate from established templates or patterns without team approval.

Which markup is used does matter:

  • Use the most meaningful yet minimal markup required to present the styles and interaction required.
  • Application-centric deliverables often have different types of requirements; please code accordingly.
  • Maintain a clear separation of concerns, avoid in-line styles and in-line JavaScript whenever possible.
  • Have reference implementations so that each team member knows what sorts of structures are appropriate, as well as where to add new code.
  • Build pages as a library of components, in such a way that blocks of code can be broken up and reused when implemented.
  • Be sure front-end code is compatible with destination environments and delivery platforms.

The flexible nature of HTML markup and how loosely browsers interpret markup sometimes lends itself to inconsistencies not always being discovered immediately. This belies the care necessary in crafting a document's structure and in following established patterns.

Indentation in HTML

[#] [Edit on Github]

Indent nested elements and tags with single indentation settings, whatever they may be, for each level in the hierarchy of the document.

<div>
    <p>Lorem ipsum Lorem ipsum dolor sit amet, consectetur adipisicing.</p>
    <ul>
        <li>tempor incididunt ut labore. et dolore magna aliqua.</li>
        <li>quis nostrud exercitation ullamco.</li>
        <li>cillum dolore eu fugiat nulla pariatur.</li>
        <li>proident, sunt in culpa qui officia.</li>
    </ul>
</div>

HTML5 Elements

[#] [Edit on Github]

To provide additional semantic value to our documents, make use of HTML5 elements such as <header>, <article>, and <section> where appropriate.

<header class="global-header">
	<main class="main-content">

	</main>
</header>

Attribute Values

[#] [Edit on Github]

Use quotes to surround all attribute values in HTML, despite quotes being optional in HTML5. This maintains consistency between attribute values that contain whitespace and those that don't.

<form class="registration module" action="/register" method="POST">

For boolean attributes that don't normally require values, include them anyway in order to remain compatible with XML based CMS's that have a more strict parser.

<input type="checkbox" checked="checked" />

Paragraphs

[#] [Edit on Github]

Avoid using <br> tags to separate paragraphs or lines of text. Use <p> instead with proper opening and closing elements.

<p>
	Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>

Definition Lists

[#] [Edit on Github]

Use definition lists to display a single record of name-value pairs, like a contact card.

<dl>
  <dt>Firefox</dt>
  <dd>
    A free, open source, cross-platform,
    graphical web browser developed by the
    Mozilla Corporation and hundreds of
    volunteers.
  </dd>

  <!-- Other terms and descriptions -->
</dl>

Tables

[#] [Edit on Github]

Tables should not be used for page layout; only use them when you need to display tabular data. Tables provide an important semantic association (used mostly by screen readers for the sight-impaired) between row/column headers and their data, so use <table> rather than other elements when displaying multiple records of data.

The <caption> element is the recommended way to describe a table for both sighted and sight-impaired users, though this can also be done less semantically in the normal page text around the table. Use the <thead> and <tbody> elements to denote which row contains column headers so when a user prints the website and the table runs onto another page, browsers can display the <thead> on each page for easier readability. Remember to use the scope attribute on the <th> element to indicate whether the header applies to the row or column.

<table>
    <caption>First two U.S. presidents</caption>
    <thead>
        <tr>
            <th scope="col">Name</th>
            <th scope="col">Took office</th>
            <th scope="col">Party</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>George Washington</td>
            <td>April 30, 1789</td>
            <td>n/a</td>
        </tr>
        <tr>
            <td>John Adams</td>
            <td>March 4, 1797</td>
            <td>Federalist</td>
        </tr>
    </tbody>
</table>

Forms

[#] [Edit on Github]

For both semantic and functional reasons, we make full use of the <form> tag for all sections requiring user input. All form action attributes should point to URLs with user-readable content, so they will still work if the form is submitted by the user before JavaScript has loaded on a page, or if JavaScript is broken, disabled, or not supported. This will require that the back-end be able to return a full HTML page for form submission (e.g. registering a new user, editing the quantity in a shopping cart).

Form tags should have a container inside that holds the inputs. Do not place the inputs directly inside a form tag. A <fieldset> tag is suitable for this purpose. You can also use <legend> to describe sections of a form.

Forms should have a name and ID.

Do not nest the HTML form element tag inside another form tag.

<form action="/handler.aspx" method="POST" name="contact" id="contact-form">

	<fieldset>

		<legend>Name</legend>

		<label for="first-name">First Name</label>
		<input type="text" name="first" id="first-name" placeholder="Enter your first name" />

		<label for="last-name">Last Name</label>
		<input type="text" name="last" id="last-name" placeholder="Enter your last name" />

		<input type="submit" />

	</fieldset>

</form>
Input Labels
[#] [Edit on Github]

All input fields should be associated with a <label> element. The for attribute of the <label> element should contain the ID of the corresponding input field. This means the input field will receive focus when a user clicks the label and also enables screen readers for sight-impaired users to read out an appropriate description of the input field.

<label for="home-address">Home Address</label>
<input id="home-address" type="text" />

You can also, alternatively, place the input for the label inside the label itself. This allows you many style opportunities to use the label as a container to align or place the form element in specific configurations.

Input controls must also have a name attribute. This can match or be similar to the id attribute. This is required for any backend integration, as the server sees the name as the key when the form is submitted.

<label for="home-address">
	<span>Home Address</span>
	<input id="home-address" name="home-address" type="text" />
</label>

Wrapper vs. Container

[#] [Edit on Github]

Consider using a wrapper inside module/partial blocks instead of using an outer container. The outermost tag of a module/partial can be devoid of padding or specific dimensions, allowing for various styles of formatting like centering elements.

<!-- preferred -->
<header>
    <div class="wrapper">

    </div>
</header>

vs.

<!-- sometimes necessary but prefer to avoid -->
<div class="container">
    <header>

    </header>
</div>

Grid System

[#] [Edit on Github]

All projects will use the latest (or highest internally supported) version of Zurb's Foundation framework. Grad classes can be used to define the layout of the page, but their use is not required.

BarkleyREI currently implements Foundation 6.3.0

Example:

<div class="row">
	<div class="small-2 large-4 columns"><!-- ... --></div>
	<div class="small-4 large-4 columns"><!-- ... --></div>
	<div class="small-6 large-4 columns"><!-- ... --></div>
</div>
<div class="row">
	<div class="large-3 columns"><!-- ... --></div>
	<div class="large-6 columns"><!-- ... --></div>
	<div class="large-3 columns"><!-- ... --></div>
</div>
<div class="row">
	<div class="small-6 large-2 columns"><!-- ... --></div>
	<div class="small-6 large-8 columns"><!-- ... --></div>
	<div class="small-12 large-2 columns"><!-- ... --></div>
</div>
<div class="row">
	<div class="small-3 columns"><!-- ... --></div>
	<div class="small-9 columns"><!-- ... --></div>
</div>
<div class="row">
	<div class="large-4 columns"><!-- ... --></div>
	<div class="large-8 columns"><!-- ... --></div>
</div>
<div class="row">
	<div class="small-6 large-5 columns"><!-- ... --></div>
	<div class="small-6 large-7 columns"><!-- ... --></div>
</div>
<div class="row">
	<div class="large-6 columns"><!-- ... --></div>
	<div class="large-6 columns"><!-- ... --></div>
</div>

For additional examples and more information on Foundation's grid, visit the Zurb Grid documentation site.

Getting Started on Markup

[#] [Edit on Github]

When crafting the HTML for a website, environment or technical constraints may impact the type of markup that can be used. Please discuss the final delivery environment in depth with technical leads and clients so that pages are not structured or styled in some way that is not effective for the project solution.

Discuss types of:

  • Templates and types of pages.
  • Which sections of pages (i.e. components) are reused or managed by software vs. by hand.
  • Frameworks, CSS grid systems (custom or otherwise).
  • Server-Side delivery platforms.

Note that it is vital to take into account how the site will ultimately be maintained and who will be doing that work.

HTML Markup Best Practices

[#] [Edit on Github]

As noted these guidelines are flexible for projects as long as consensus or need determines a particular path, consistency is what matters most.

Semantic Markup

[#] [Edit on Github]

HTML provides a number of semantic constructs that allow automated tools like search engines and screen readers to make sense of the document and to understand relationships between pieces of content. Use semantic markup whenever possible — that is to say use elements with specific meanings for specific purposes to convey the spirit of the markup.

A well-written HTML document will make appropriate use of these semantic elements and leave all responsibility for controlling the presentation of the document to the CSS style sheet.

HTML Standards and Browser Support

[#] [Edit on Github]

All markup will be written using the latest HTML5 markup specifications from the W3C, as implemented by browsers and devices that meet project requirements. When creating markup be sure that the target environments support the techniques being implemented, or that there is a fall-back plan.

Modernizr includes the HTML5 Shiv to allow HTML5 support for older browsers. Modernizr is a standard part of the app generator.

Learn more:

You will frequently hear the term "polyfill", "shim", or "shiv" passed around where backwards compatibility for HTML5 and older browsers is concerned. What is a Polyfill?

Doctype

[#] [Edit on Github]

Always include a proper doctype to trigger standards mode. Omitting the doctype triggers quirks mode and should always be avoided. The HTML5 doctype is simple and easy to remember.

<!doctype html>

Character Encoding

[#] [Edit on Github]

All markup should be delivered as UTF-8, since it has the best support for internationalization. The character encoding should be designated in both the HTTP header and the head of the document via a meta tag. If the server happens to omit the HTTP header, browsers can take a guess at the character encoding and begins parsing and rendering the markup in a particular way. If there are inconsistencies, the browser will re-parse and re-render, throwing away all that work and starting over if it encounters the meta tag and its guess was incorrect. As a best practice, we always put the meta tag as early in the <head> tag as early as possible — however server-settings are ideal.

<meta charset="UTF-8" />

Optional and Self-closing Tags

[#] [Edit on Github]

Include slashes in all self closing tags for compatibility in older, XML based CMS's. Include all closing tags, even if they are technically optional.

<!-- closing "/" is not necessary but should be included for compatibility -->
<img src="/logo.png" alt="ISOBAR" />

<!-- include closing tags always -->
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit:</p>
<ul>
    <li>Vero sunt veritatis magni sit odit,</li>
    <li>voluptatum ratione suscipit.</li>
</ul>

Unusual markup (or indeed, invalid) can lead to bugs in page rendering, DOM interpretation, or even how styles are applied, so it should be avoided whenever possible.

Note:

While a library like jQuery might recognize tags that are not typically self closed (e.g. <div />), it is recommended to avoid this usage directly in your markup, as some browsers choke on it.

Validation

[#] [Edit on Github]

Valid markup is a goal but not a mandate. However, be aware validation can be an excellent starting place while debugging a Web page — especially if the problems are unusual.

If it becomes necessary, please have reasons for invalid markup — otherwise it is just sloppy code.

For W3C validation, we will strive to resolve as many reasonable issues that come up from validation as possible, but it should be understood that it may not be possible to resolve 100% of the issues. This should be reviewed by the developer and each issue considered for validity.

CSS

[#] [Edit on Github]

Cascading Style Sheets (CSS) is where the visual presentation and design rules for a website belong. Well-written CSS makes good use of its cascading nature - general styles are applied first, and those styles are overridden for more specific instances as necessary.

Goals for Effective CSS

[#] [Edit on Github]

CSS is an unusual language which can easily lead to code bloat, inconsistencies in design or clashing code techniques. It is easy to end up with CSS code that is so fragile it can cause site-wide regressions with small changes.

CSS should:

  • Be easy to maintain.
  • Follow clear enough patterns to understand.
  • Offer a clear place for new styles going forwards.
  • Not be a drag on page loading performance.
  • Not include unused style rules.
  • Address different devices, browser versions, and do as much as it can with as little code as possible.

When setting up the CSS for a site, always consider:

  • What the default styles for HTML elements are going to be.
  • Which styles are global styles versus template specific styles versus specific one-off use-cases. (Rule of Three)
  • Distinctions between code for layout and for content.
  • How the code will evolve and grow.
  • Potential impact of bug fixes on the overall site.
  • Use of images as CSS background images vs. in-line HTML (content).

SCSS-Lint

[#] [Edit on Github]

All BarkleyREI projects are linted by SCSS-Lint to detect and alert style issues with SCSS files. We adhere to all the defaults located here with the exceptions of the following:

  • DeclarationOrder is set to false
    • This causes issues with Foundation's breakpoint() mixin.
  • EmptyRule is set to false
    • These are removed in the final compiled file anyway, and this plays nice with our generator.
  • HexLength is enabled and set to “long” (requiring 6 characters always)
  • ImportPath has leading_underscore set to true
  • Indentation has character set to “tab” and width set to “1”
  • LeadingZero is enabled and style set to “include_zero”
  • NestingDepth is enabled and max_depth is set to “4”
  • PropertySortOrder is set to false
    • This is difficult to enforce but we may pursue this later.
  • PseudoElement is set to false
    • I've noticed that two colons fails in some browsers but I'm not certain.
  • QualifyingElement has “allow_element_with_attribute” set to “true”
  • SelectorDepth has “max_depth” set to “4”
  • SpaceAroundOperator is set to false
    • Requested by Sarah and approved by Ian
  • TrailingWhitespace is set to false
  • TrailingZero is set to true
  • TransitionAll is set to true
    • You should only transition specific properties

Excluding SCSS from linting should be avoided, but in the fringe case that you must remove linting from a specific section of a SCSS file, this can be achieved by the following example:

.search {
	// scss-lint:disable VendorPrefix
	::-webkit-input-placeholder {
		color: $placeholder-text-color;
		font-style: italic;
	}
	// scss-lint:enable VendorPrefix
}

You must always deactivate only the rules you need, for only the lines you need. If an entire scss file needs excluded from linting, one of the following must occur:

  • It should be rewritten so that it passes without disabling rules.
  • It should be rewritten so that only the affected lines are excluded.
  • It should be moved to an excluded directory (like plugins, if you are importing styles from a third party component).

Resources:

Specificity

[#] [Edit on Github]

Use the minimum specificity required to achieve the desired style. It can be difficult to quickly read and locate styles or even bugs with heavily nested styles in the CSS.

The ID is the most specific selector, since it can only match one element, and the class is a close second. Use those whenever possible rather than HTML tag names.

/* BAD */
button#back-button { ... }
.popular ul li a { ... }
.popular > ul > li > a { ... }

/* GOOD */
.back-button { ... }
.popular-link { ... }
.unpopular-link { ... }

As a rule, CSS is most maintainable with the simplest selectors possible. Try applying a class to the element you want to target instead.

Note:

While performance of CSS selectors has been a debated topic, browsers perform quite well on most types of selectors. That said, specificity reduced to the most simple name to get the desired results is the best idea in most cases for readability and maintainability.

Do Not Use !important

[#] [Edit on Github]

Avoid using the !important keyword. Treat it like the nuclear option, only to be used in the most extreme of cases. This fundamentally destroys the specificity feature and can even break accessibility for some users.

There is usually another way to achieve the same goal without causing headaches for developers in the future who are either trying to debug a styling issue, or trying to use normal specificity to override a style for a particular element only to find that they can't.

ID Selectors

[#] [Edit on Github]

As noted above, use the lowest level of specificity necessary to get the desired results. This means the use of the ID selector should be minimized. Often creating a new class is preferable to using inheritance or additional specificity to target an element or elements.

ID selectors, if used, should be used mainly as access points for JavaScript or if a very particular use case surfaces. Styles and classes can be applied via the same element with a className.

SCSS Lint will flag the use of IDs, so if they are absolutely required, they must be excluded via scss-lint:disable statements.

Vendor Prefixes

[#] [Edit on Github]

There is no need to manually type vendor prefixes. They will be automatically included by autoprefixer when the project is compiled. If your desired vendor prefix is not appearing, check the browserlist settings in your project. If you have to manually type a vendor prefix, put the standardized rule at the end to ensure browsers optimize and use the standard if they recognize it.

For example:

.thing {
    -webkit-transition: all 100ms;
    transition: all 100ms;
}

Inline Styling

[#] [Edit on Github]

Do not hard code style information into your HTML markup directly, either with the style attribute that accepts CSS or with deprecated attributes such as align, border, or width. These are difficult to maintain and make it harder to track down what is causing an element to appear as it does.

There are a few exceptions to this:

  • Background images that are changeable by the client.
  • Positioning of captions in mastheads using percentages or pixels via top/left/right/bottom.

Performance Caveats

[#] [Edit on Github]

In some cases for performance reasons it may be good practice to in-line critical styles in a style block in the document's head. This delivers these styles to the browser in the fastest method possible by preventing the need for an additional HTTP request. Fetching linked style sheets are a blocking operation on the rendering of a Web page in a browser in most cases. An enormous CSS file can mean a highly reduced time to first rendering because a browser may pause during loading of the page to download CSS which may not even be used on the first page.

With the above in mind it may be desirable to include the rules required to render the top portions of a page (i.e. "Above the fold") in advance of styles loaded after the rendering begins. Critical styles can be identified either manually or through the use of a tool. Non critical styles can then be asynchronously loaded, increasing the perceived page load speed.

BarkleyREI does not currently implement critical styles as a technique.

Box Model

[#] [Edit on Github]

To simplify CSS authoring, we set the box-sizing attribute to border-box for all page elements. This enables us to use round numbers for width like 50% and then apply a padding or border to that same element without needing to

  1. adjust the width accordingly using calc (since borders use pixels rather than percents) or
  2. create an element inside it to take the padding and border. This is the only case where we use the inefficient universal selector (*).

Example:

* {
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}

Coding Patterns

[#] [Edit on Github]

There are a number of popular design patterns for naming conventions on selectors, groupings or extensions of styles in CSS files. Sometimes these are of value and may be used on projects as long as the developers are on board and they are used consistently by the team.

Examples of pattern systems include BEM, SMACSS, Object Oriented CSS, Atomic design, and others.

The downsides to some of these systems are:

  • Often rely on less obvious rules that may be difficult to follow.
  • They may use syntax that may be objectionable to some developers.
  • Some developers may find the syntax difficult to read.

For these reasons it is often best to go with the most simple, basic set of conventions possible, based on obvious patterns.

BarkleyREI does not currently follow a popular coding pattern for CSS/SCSS.

A Simple CSS Code Pattern

[#] [Edit on Github]

The following sections describe one simple approach, and as long as the types are defined on a project and the patterns are followed, then a clear meaning can be interpreted fairly quickly and easily reading through the CSS, HTML, and JavaScript.

Every site will have distinct requirements but some examples of things that can be standardized on a site build include:

  • Global Defaults
  • Page Level Rules (grids, site template types, and so on)
  • Components
  • Modifiers
  • State
  • JavaScript-only Rules
  • Utilities

The following sections describe how some might work.

Sass

[#] [Edit on Github]

All styles should be written in Sass (Syntactically Awesome Style Sheets) unless specifically requested otherwise by management or the client. The structure of the Sass in the project should follow the SCSS Boilerplate on our Github.

Refer to the "Formatting SCSS" section of this document for more information on writing Sass styles.

Global Defaults
[#] [Edit on Github]

For the purposes of discussion we could refer to the global defaults as the baseline HTML elements and their associated styles. Frequently you may wish to use a third party library which normalizes CSS behavior across browsers. Either way, it makes sense to keep these files in their own files.

BarkleyREI uses Foundation to reset styles, which in turn uses Normalize.css.

Print styles should be contained within a separate stylesheet, and should be applied with <link> tags set to the appropriate media statement so that they style the unstyled document.

<link rel="stylesheet" media="screen" href="main.css" />

<!-- print styles are seperate and style the plain document -->
<link rel="stylesheet" media="print" href="print.css" />
Page Level Rules
[#] [Edit on Github]

Any site is liable to have a standard baseline set of grids and types of pages. These grids can be collected into their own distinct set of component files — using a broad definition of a global "thing" as a component.

Markup Deliverables

[#] [Edit on Github]

Typically HTML deliverables are incorporated into CMS's or application delivery platforms as templates. A plan for incorporation of templates that leverage patterns created during the markup creation phase should be followed and matching types of pages to templates that were created, so that an association between the source markup and the destination markup can be maintained over time.

If the templates built are not being integrated into a CMS by BarkleyREI, the static coded versions of these templates can be provided as a deliverable.

Components
[#] [Edit on Github]

Components are a high level concept for organizing CSS files and rules. A component simply means a grouped set of rules pertaining to an object or set of related objects on a page.

Additionally, encapsulating these components into distinct files is a great option. Within this file, using a naming convention is a tremendous help here for code maintainability and readability.

Group styles under a simple name-space using a prefix-suffix-modifier type pattern such as:

/* core component */
.component { ... }

/* component elements */
.component-header { ... }
.component-content { ... }

/* component descendant */
.component-content-group { ... }

/* component descendant element */
.component-content-group-header { ... }
.component-content-group-imgs { ... }

This type of pattern is easy to read, extend, and follow in the absence of something more sophisticated.

Additionally, generally components will be the only CSS class with distinct names that do not have prefixes before the core, root, or base name of the component (e.g. above we are using component).

Just to get developers thinking, these might be things like:

  • navbar
  • footer
  • page-info
  • article-date
  • lead
  • widgetfoo
  • byline

Next Steps & HTML5 Resources

[#] [Edit on Github]

Considerations:

  • Site maintenance procedures.
  • Browser testing strategies.
  • How new features will be added.
  • Where new features will be added.
  • What the file system looks like for static site assets.
  • If a CDN is involved.
  • Naming conventions and organization of graphics and photography assets.
  • If the "back-end implementation" of static HTML templates will require review by front-end team members.

Modifiers
[#] [Edit on Github]

If you need to extend an existing component then create distinct modifier classes to easily indicate that it is a modifier and not a complete style. Using a prefix can prevent confusing the class with a full class. In the examples below, we are using the mod- prefix to identify modifiers.

.mod-modifier-a { ... }
.mod-modifier-b { ... }

Then, when used in the HTML, the class stands out:

<div class="component-content mod-modifier-a">...</div>

This is a strong technique because the modifier classes can stand on their own in the CSS. Further, they may also be altered via more complex rules:

.component-header.mod-modifier-a { ... }

This is simplistic and easy to follow, understand, and expand upon.

State
[#] [Edit on Github]

A state for an element or component is presentation information for a given component. This may be a dynamic state set by JavaScript or a user interaction, but not always. It could also be a preset from the server or the results after a transaction. State modifiers are a great way for a distinct class to be provided to engineers unfamiliar with the design, to give them hooks for various behavior. This is slightly different than JS specific classes, however.

State rules will use the is- prefix.

.component-group.is-full { ... }
.component-group.is-expired { ... }

Treating components' state as a modifier that is boolean (i.e. true or false) also:

  • Semantically helps provide information about the content.
  • Separates the code for state from default presentation.
  • Removes the need to update corresponding states or components if the name of either changes.

This last point is important from a maintenance perspective.

It's best to try to restrict these state indicators as being restricted to a specific component.

JavaScript Behavior Prefixes and Classes
[#] [Edit on Github]

The usage of a js- prefix is present in the markup but should never really appear in the CSS file itself. If the styles are being set, then use modifiers or state type classes.

<button class="component-button js-execute">...</button>

The js-execute rule should not appear in the CSS file, but only in JS files they are tied to behavior. These are events, verbs, or action related, and are access points for JavaScript not a toggle or state changer. It's best to think of these classes as closer to and ID attribute in the HTML.

The .no-js class can be used to add behavior to a component when JavaScript is disabled or otherwise unavailable to the page. This class is added by default to the <html> tag and is removed by Modernizr when the page loads.

Special attention should be paid to components that are enhanced with JavaScript to ensure that their behavior is reasonable when JavaScript is not available. Some examples include:

  1. Showing a rendered slide of a carousel without the paging functionality.
  2. Opening all accordions by default.
  3. AJAX driven functionality is linked so that it will click through to a query-string enabled page that supports the same functionality that was implemented using AJAX.
    • For example, on a faceted search, a user may be able to click on a category and will be taken to /results?category=1 where the results will be filtered to the category they selected.
  4. Result sets can be filtered and paged using query strings.
  5. Functionality that cannot exist without JavaScript at all should have an explanatory message shown to the end user to explain the issue.
Utilities
[#] [Edit on Github]

A utility is a type of component modifier that is specifically designed to be used on more than one component type. If it was restricted to a single component, it would simply be a modifier.

Utilities should serve only the modifier purpose intended without side effects when applied to any component, or component descendant. In the examples below, the prefix u- is being used for utilities.

.u-warning {

}

.u-scroll-infobox {
    overflow-x: scroll;
    width: auto;
}

The Mobile Web, Media Queries, Responsive Design

[#] [Edit on Github]

With the mobile Web taking off Media Queries are mandatory in CSS going forwards. All styles should be written mobile first, with limited exceptions.

We discuss media queries in the Mobile / Responsive section of this document.

CSS Deliverables

[#] [Edit on Github]

Please be aware of potential conflicts between the original development environment for CSS and an ultimate deployment to production systems, if continuous integration will allow the continued use of CSS preprocessors, or if there should a cross-platform development strategy.

Delivered CSS should be concatenated, minified, tested against browser bugs (e.g. MSIE selector count bugs) and extra files should be removed.

File naming conventions should be consistent and language or use-case specific files should be clear and not be easily confused with the global style CSS.

Uncompiled SCSS files can be provided to the client upon request. Appropriate documentation should be given on how to compile them.

Next Steps & CSS Resources

[#] [Edit on Github]

This is just the tip of the iceberg where CSS is concerned.

  • Browser Compatibility
  • Media Queries
  • Accessibility and CSS
  • CSS pre-processors usage
  • Internet Explorer, or browser-specific bugs
  • Usage of CSS3 transitions, transforms, and more
  • Vendor prefixes
  • Color Management

Frameworks

[#] [Edit on Github]

Unless specified otherwise, all projects should use Zurb's Foundation framework. The grid system, reset, and default styles will be included by default.

Only use components and features from Foundation as they are needed. Do not include anything unnecessarily, as this adds to overall bloat.

If other frameworks are desired by the client or management, best care should be taken to minimize the total size of the final CSS file. This can be accomplished by separating out the bulk of the framework into a separate or CDN-hosted CSS file that is referred to before the main styles.

Establishing Conventions and Development Strategies

[#] [Edit on Github]

Like other aspects of the code on a site, consistency is key. Areas of critical consistency include:

  • Code formatting.
  • Naming conventions.
  • File and folder structure.
  • Examples or sample code.
  • How page components might be broken down or re-used.

On a large site never develop using a single CSS stylesheet, though a single file served for a page is best. To this end we often recommend the use of CSS preprocessors to break style sheets into smaller, better organized files, or the use of a build process to combine files for serving via HTTP.

Try to use the rule of three when building stylesheets for a website:

  • Global site styles (Main.css).
  • Template specific styles (Level vs. Home).
  • Feature specific styles (One off page).

Note:

It is a great idea to approach front-end development like a set of reusable components are being created. This matches how they are designed, how they must adapt to responsive layouts, and how they will be implemented inside content management or other server-side frameworks.

Resources:

Living Style Guides and Reference Implementations
[#] [Edit on Github]

One technique to consider is maintaining static HTML style reference implementations well into integration with server-side / back-end systems. Because BarkleyREI statically codes all designs and submits them to Quality Assurance Testing before integrating into any CMS's, these files are a reference for the global styles of the site and a great place to code and test additions to the project before integrating. This helps reduce regressions that can happen across the board as the code for the site evolves. Continue to test these reference implementations as they will be the "source of record" for the styles created on the site. They also allow you to more easily distinguish the front-end bugs from the bugs potentially introduced by integration with a complex back-end.

These reference implementations can serve as a living style guide and broken components are easily spotted in testing over time.

Defining a solid style guide to be applied to tag names can significantly reduce the size of the CSS if that style guide is adhered to by both the design and development teams. It is recommended that a style guide is agreed upon at the beginning of a project, defined in HTML and then iterated on by both the design and development teams.

For BarkleyREI's purposes, the living style guide can be satisfied by the statically coded templates. All new work should be done statically and tested before integrating into a CMS. Care should be taken to maintain the integrity of the existing styles and markup, and maintain parity with the CMS-integrated versions.

CSS Best Practices

[#] [Edit on Github]

What follows are some basic concepts for standardization of CSS code. Naturally, feel free to fork, update per project, and even issue pull requests for further discussion based upon experience.

Inclusion

[#] [Edit on Github]

Use the <link> tag to include all your style sheets in the <head> of the document. For optimal page performance, concatenate your CSS into as few files as possible and do not use the @import command to include other style sheets, as this will fire an additional HTTP request and block page rendering until its completion.

<link rel="stylesheet" type="text/css" href="main.css" />
<link rel="stylesheet" type="text/css" href="home.css" />

Formatting CSS

[#] [Edit on Github]

The majority of CSS produced by BarkleyREI will be compiled from SCSS, but in the odd occasion that we must write normal CSS for a project, please adhere to the following rules.

Basic rules for formatting CSS files:

  • Use a new line for every selector and every declaration.
  • Use a single space before the opening brace in a set of rules.
  • Use lowercase for elements and longform hex values, e.g., #aaaaaa.
  • Hyphenate class selector names; avoid underscores and camelCase.
  • Quote attribute values in selectors.
  • Use one level of indentation for each declaration.
  • The closing brace of declaration goes in the same column as the first character of the set of rules.
  • Use a single blank line between sets of rules.

Inside sets of rules or style declarations:

  • Add a single space between the property and value, for example:
    • prop: value; and not prop:value;
  • Use double quotes for quoted values.
  • Always include a semicolon at the end of the last declaration.
  • Use shorthand if you can, like:
    • padding: 15px 0; and not padding: 15px 0px 15px 0px;
  • When allowed, use 0 without units.
  • All font families must have fallbacks to web safe fonts (e.g. serif, sans-serif).

Putting each selector on its own line and each property on its own line is great for readability and so version control systems can clearly show which parts have changed in a diff.

The attributes within a selector can be alphabetized for easy scanning and so that compression algorithms like gzip have a greater chance of finding repeatable patterns.

Some examples:

.content {
    margin-left: -2%;
}

.twitter-popular,
.twitter-favorites,
.twitter-feed {
	background-image: url("/img/bg.png");
    float: left;
	padding: 15px 0;
    width: 33.33%;
}

Do not indent child styles underneath their parent styles; this is important for a number of reasons:

  • Some CSS preprocessors heavily use indentation.
  • Various levels of indentation hinders maintainability.
  • HTML and CSS structure can change frequently over the course of a project, quickly rendering obsolete the parent-child relationship the indentation used to represent.

Formatting SCSS

[#] [Edit on Github]

Basic rules for formatting SCSS files:

  • The ordering of styles should be:
    1. @extend
    2. @includes (without inner content)
    3. Regular styles
    4. @includes (with inner content)
    5. Nested rule sets
  • Nested rule sets should follow the same ordering of styles.
  • Foundation breakpoints should be placed inside the selector they directly affect, and should not contain nested styles.
  • Nesting shouldn't go deeper than 4 levels.
  • Nested statements shouldn't be longer than 50 lines.
    • This means that each nested selector shouldn't total 50 lines, not that the entire file should be under 50 lines. This is so that a nested selector can fit into your editor window to reduce confusion during development.
  • Only use variables or functions for colors in a module/partial.
    • Try to use specifically named variables instead of the raw color names. For example, $header-outer-border-color instead of $congress-blue;.
    • The palette helper is also recommended to assist with naming.
  • Surround all pixel values in rem-calc().
    • Exceptions are permitted where rem units are not supported or cause issues (like borders).

Inside sets of rules or style declarations:

  • Omit an empty line between the top and bottom of a nested block.
  • Add empty lines in between nested blocks.
$palettes: map-merge($palettes, (
    'accordion': (
        'core': $black,
        'background': $iron,
		'title': $midnight-blue,
		'hover': $mango-tango,
		'border': $mango-tango
    )
));

// Example, normally this would be in theme-variables.scss
$default-font: 'Lato', Arial, sans-serif;

.accordion-item {
	@extend %list-reset;

	border-top: 1px dotted $dodger-blue;

	&:first-child {
		border-top: 1px dotted palette('accordion', 'border');
	}

	.accordion-title {
		color: palette('accordion', 'title');
		display: block;
		font-size: rem-calc(24);
		line-height: rem-calc(28);
		position: relative;
		padding: rem-calc(15 20 15 28);

		@include breakpoint(large) {
			font-size: rem-calc(30);
			line-height: rem-calc(34);
			padding: rem-calc(17 20 17 42);
		}

		.no-js & {
			padding-left: 0;
		}

		&:hover,
		&:focus {
			text-decoration: none;
		}
	}

	.accordion-content {
		background-color: palette('accordion', 'background');
		display: none;
		padding: rem-calc(25 25 25 0);

		.no-js & {
			display: block;
		}
	}
}

JavaScript

[#] [Edit on Github]

JavaScript is where extra behaviors, features, and functionality not offered natively by Web browsers through CSS and HTML is created.

JavaScript has gained an enormous amount of attention in recent years due to more feature rich, faster browsers and server run-times such as Node.js. For the purposes of this document, general discussion here focuses on client-side JavaScript development, with references to where it crosses over.

It is of note that many techniques identified these days as "HTML5" are actually enabled by the related JavaScript APIs.

Goals

[#] [Edit on Github]

Unless we are talking about a complex client-side Single Page Application (SPA), JavaScript should be used sparingly, and when a deliberate choice is made to not perform a task with other available technologies. The decision to add more scripts to a Web page should be made carefully. Even with a SPA, it is critical to make controlled choices so as to not include too much unorganized impossible to maintain code.

Any and all JavaScript code that's added to a Web page should be there if and only if it is needed for the page to achieve the desired ends or if there aren't any negative impacts with it there.

Included JavaScript should:

  • Be included after careful consideration.
  • Have the performance overhead and file size evaluated.
  • Have a feature set that is understood and appropriate.
  • Perform only the necessary tasks without needless overhead.
  • Have maintainability carefully assessed.

While being:

  • Fast, efficient, and perform well.
  • Re-usable if possible.
  • Not conflict with other code on a given page or sets of pages.
  • Executed only when necessary on a given page or sets of pages.

Likewise, the absence or failure of the code should be carefully considered:

  • What happens if for some reason this code is missing or does not run?
  • What happens if the code triggers an error?
Writing and Formatting JavaScript
[#] [Edit on Github]

The use of whitespace should follow long-standing English writing conventions, with blank lines between ideas and groups of code such as objects, functions, and new lines for new statements.

Formatting the language statements and patterns should follow these basics:

  • For named functions, do not insert a space character between the function name and the parentheses.
  • For anonymous functions, do insert a space character between the function keyword and the parentheses. It’s a function definition; it’s not a function invocation. A space character helps to identify, and communicate, the difference between the use of functions.
  • Open braces are preceded by a single space.
  • Open braces should appear on the same line as their preceding argument.
  • Close braces should appear at the same indentation as the statement preceding the opening brace
  • There should be no space characters between parentheses and their contents.
  • Use semicolons and do not rely on automatic semicolon insertion.
  • Each comma and colon (and semi-colons that don't end a line) should be followed by a single space.
  • Binary and ternary operators should have a single space on each side.
  • Quoted values should be in 'single quotes' so that double quotes may easily exist inside them.
  • Comment JavaScript code thoroughly and consider using a pattern such as those described by JSDocs so that documentation may be generated automatically.
  • Conditional statements go on a new line followed by the opening brace.
  • Else/else go on the same line as the brace.
  • Use type strict checks with === as opposed to == whenever possible.
  • Use += and -= instead of ++ and --.
var len = arr.length;
for (var i = 0; i < len; i += 1) {
    var example = 1;
    if (example === i) {
        // we are looping
    } else {
        // this will never happen
    }
}

To maximize readability without worrying about which boolean operators bind more tightly than others, each segment of a boolean expression should be enclosed in parentheses.

if ((allowUpdate) && ((user.isAdmin) || (user.role === item.owner))) {
    // do something
}
Variable Declaration
[#] [Edit on Github]

To avoid confusion between global and local variables, we declare each variable on its own line with the var keyword. We do not use a single var keyword and then chain several variable declarations onto it separated by a comma.

var windowWidth;
var windowHeight;
var currentVal = $(this).val();
var min = parseInt($(this).attr('min'), 10);

This has been debated at length, however we believe this is a better practice due to several technical reasons:

  • Easier debugging with debuggers.
  • Easier merges with version control and diff utilities.
  • Most technical issues are resolved by 'use strict'.

Fallback values should also be considered when declaring variables whose values may be omitted or missing by the calling function.

var subhead = $('.thing').val() || '';

The || syntax may not work in all situations, so it may be better to write a standard function that can do null-checking of values and pass all requests for data through that function.

Variable Scope
[#] [Edit on Github]

Minimize the use of global or window level variables and name-spaces. Pollution of the global name-space is error prone and a bad practice.

If referencing a window or global level variable that isn't obvious, please comment as such or explicitly state it.

var window.thing = {};
Variable Names and Types
[#] [Edit on Github]

Always use meaningful variable names that can be read as words, not as silly abbreviations only you understand.

  • Variable names should be camelCase.
  • Objects, classes, and name-spaces should be TitleCase.
  • Boolean values should be prefixed with is if at all possible.
  • Cached jQuery objects can be prefixed with $.
  • Use shorthand versions of empty Arrays and Objects.
// some examples
var exampleValue = 'my example variable value';
var numberOfTimes = 3;
// booleans
var isThisWorking = true;
var isNotWorking = 0;
// cache a selector
var $body = $('body');
// short hand objects and arrays
var newObject = {};
var newArray = [];
Settings, Constants
[#] [Edit on Github]

Put settings together in obvious places such as an Object literal space inside your module. Make settings that are possibly to be considered "constants" to be obvious -- some developers like to use ALLCAPS.

Learn more:

Did you know that ES6 now features real life constants?

Feature Detection
[#] [Edit on Github]

Always test for the existence of a browser API, function, or object property before you use it, and make sure the user experience is still functional (to the extent possible) if it's not found. We rely on JavaScript-based feature detection rather than server-side device detection because it's more robust, easily maintained, and future-proof.

Learn More:

The goto library for feature detection is of course Modernizr.

Limit Events - Use Event Delegation
[#] [Edit on Github]

It is always preferable to use fewer events being bound to objects on a page as possible. Too many events bound on a page can mean memory leaks or just an accumulation of handlers bound to DOM elements which becomes less and less efficient over time. Additionally, event delegation has the added benefit of persisting events over dynamic page updates when items are added or removed from the DOM.

With jQuery this is easy, simply use the on method with a selector:

// jQuery
$(‘body).on(‘click’, ‘.a.scrollbar’, function () {
	// this only runs if the a.scrollbar is matched
});

// JavaScript
document.body.addEventListener(‘click’, function (event) {
	var event = event.target;
	if (target && target.nodeName.toLowerCase() === ‘a’) {
		if (target.classList.contains(‘scrollbar’)) {
			// this only runs if the a.scrollbar is matched
		}
	}
}, false);

Learn more:

The jQuery API site has an excellent overview of the on method.

JavaScript Performance
[#] [Edit on Github]

One of the most costly operations a browser can perform is updating the DOM in the page via inefficient JavaScript techniques. The most important thing to know is that the more you do on a Web page with JavaScript, the more work is being done, the more memory and the bigger the footprint it can generate. Additionally, updating a complex DOM structure over and over in JavaScript can cause re-flow, repainting, and jank.

A book could be written on the subject, but here's a taste of various references:

Basic JavaScript Architecture

[#] [Edit on Github]

Today it is common for the JavaScript code on a site to be a vast collection of "Modules" brought together by build scripts, dependency tools, or even manually by the developer (not really recommended).

Smaller sites can get away with more simple structures, but for longer term, JavaScript-heavy code bases the following rule is critical:

  • For a complex site, never use a single JavaScript file for development, unless it is tiny and serves a very targeted purpose.

This is so that the code is maintainable and scalable. Smaller files are easier to debug, swap in and out, and blocks of code should serve as small a purpose as possible (single responsibility principle).

In most simple terms, most sites benefit from a basic structure similar to:

  • Global site-wide JavaScript
  • Specific modules for specific sections of the site
  • Specific modules used for specific purposes / features
  • Available vendor libraries

With this in mind, for strict control over the code base it's best to consider:

  • What is the central entry point, or the central point of execution? This is to say, what kicks off the JavaScript? This may be a simple jQuery document.ready() or some other mechanism to run the site's code, such as a router.

Having explicit control over the page life-cycle is preferable to having a dozen jQuery document.ready() statements all competing for the first chance to execute on a page.

Effectively the application core, it should kick off the rest of the code to run. Typically this has module-management baked in in some way.

Note:

One way to control which code runs on a page is through DOM-based routing.

Additional considerations:

  • How are the modules going to communicate with each other?
  • How tightly coupled are the modules in the code base?
  • How much JavaScript code would need to be updated if/when the HTML / CSS changes on the project?
  • Can individual parts call as few libraries or plugins as indirectly as possible, to facilitate changes later?
  • Does the server need to provide the scripts dynamic values for JavaScript?
About JavaScript Modules
[#] [Edit on Github]

The term "module" in JavaScript has probably been over-used. It can refer to specific patterns used by specific tools and frameworks, or simple blocks of code following some typical JavaScript design patterns.

These days options for JavaScript modules include some of the following.

Vanilla JavaScript:

Or, a common standard, used by many dependency tools:

  • AMD modules (most commonly used by require.js)
  • CommonJS modules (most common used by node.js and browserify)
  • ES6 modules

Frameworks will have their own unique set ups.

Learn more:

ES6 has just recently standardized how script loading, importing, and more about how modules will be handled as part of the standard spec going forward.

Getting Started on JavaScript

[#] [Edit on Github]

All too often a developer will solve a problem in a closed context and not consider the whole picture. "Add another plugin" is not always a good answer.

It is well worth considering if parts or all of the code being added can be useful elsewhere. Centralized code is excellent because it can be updated once and re-used everywhere.

For JavaScript, a Front-end developer should be thinking about:

  • If there is code that does this task already?
  • Code formatting rules, naming conventions, file locations, etc.
  • Testing the code on various browsers and devices.
  • If strings of text should be external for content management or translation.
  • If code being added might be useful outside of the current problem.

Examples of possible things to centralize:

  • Code that modifies the DOM
  • Ajax, validation, or other libraries
  • Query string parsing utilities, router-type code
  • Tests for global conditions (e.g. window size, feature support, etc.)
  • Page, window, or document level events (e.g. Ajax, resize, etc.)
  • UI controls (e.g. spinners, modals, tabs, etc.)
  • Date handling utilities
  • Files with strings of text in a given language
  • Finally, settings and configuration options (e.g. paths to services, debug flags, duration settings, minimum or maximum values, etc.) are common things to set in a centralized, distinct place.

Alternatively, if a problem can be solved with a custom module and not a third-party library or plugin, this solution is preferred, as it keeps the costs of the project down while not including any irrelevant or unused code.

Bottom line, please understand what the JavaScript does and how it does it if you are including third party code.

Note:

Client buy-in may be necessary for the usage of JavaScript for some features. It may be a forgone conclusion but usage of libraries or custom code should be discussed with the team and client technical leads to be certain the teams are on the same page.

JavaScript Deliverables

[#] [Edit on Github]

The most obvious fact is you will need to provide working files that are error-free and will work in a variety of scenarios. We can't assume that clients will always leave scripts and pages as we leave them, though we can provide direction as to how scripts should be used.

Understanding the Code's Place in the Project

  • Understand where your code will live vs. any code introduced in a destination environment
  • Understand if the code will need to coexist with other code.

Clean, Clear, Organized, Readable Code

  • As bug free as possible.
  • Always remember we write code for other developers, not for a runtime or a browser.
  • Remove code that is no longer used. Remove excess "noise" or distractions from source code such as large commented out blocks of unused code. Source control can solve problems like this.
  • Have console and debugging statements be removed or a plan in place for suppression during the build or deployment.

Learn more:

The Essentials of Writing High Quality JavaScript is an older article but still holds up today.

Delivery of a flat folder full of JavaScript files is not advised.


# Do not deliver the following

├── web/
│   ├── js/
│   │   ├── main.js
│   │   ├── home.js
│   │   ├── ...
│   │   ├── vendor
│   │   │   ├── source01.js
│   │   │   ├── source02.js
│   │   │   ├── ...
│   │   ├── modules
│   │   │   ├── module01.js
│   │   │   ├── module02.js
│   │   │   ├── ...

Next Steps & JavaScript Resources

[#] [Edit on Github]

There is an enormous volume of JavaScript reference material out in the wild today. Here are various topics worth following up on:


JavaScript Libraries, Frameworks, and Plugins

[#] [Edit on Github]

Recent years have seen a virtual explosion in new JavaScript libraries sometimes calling themselves "frameworks".

Libraries and frameworks can be useful, especially when the client-side is become more responsible for larger parts of applications and websites.

  • Libraries are code you use within your structure, featuring code that is available for you call upon.
  • Frameworks are code collections that serve specific purposes in a particular way, and call your code that is included following their patterns.

Learn more:

The basic idea is an "inversion of control" in the code. This is debatable, but something like jQuery could be said to be a library, while Angular, React, or Backbone could be a framework.

Either way, this is typically third party code that should be carefully considered when it is determined to be included in a project or not.

Selection of Third Party Code
[#] [Edit on Github]

Selection of a library or framework is never an easy task. Things that should be considered include:

  • Technical Requirements for the project.
  • Quality and maturity of code in question.
  • Future support for the code.
  • Staffing skill sets required to support the code.
  • How tightly coupled to the layers of the application the code may be.
  • How actively supported its open source community may be.
  • Be tested against various devices and platform requirements to verify it works for the project.
Usage of Third Party Code
[#] [Edit on Github]

Third party code should be included as-is and:

  • Treated as it may be updated (i.e. versions) at some point in the future.
  • Should never be modified unless documented thoroughly for the project.
  • As many conventions of its use followed in their recommended standard ways.
  • Un-minified code should be included.
  • Any required licenses should be included as specified by the library.
  • Commercial code must be approved if necessary.

A team may decide to write wrapper code around the third party library and provide a more simple API for the code.

ECMAScript 6, ES6, ECMAScript 2015

[#] [Edit on Github]

Developers are encouraged to begin learning and using the latest version of JavaScript, ES6. Please use appropriate transpilers and never release untested or unsupported code in the deliverables. Do not assume a feature is supported in a browser.

BarkleyREI currently writes JavaScript using ECMAScript 5 standards.

JavaScript Best Practices

[#] [Edit on Github]

The following guidelines are general best practices for writing JavaScript at BarkleyREI.

  • If possible, avoid user-agent sniffing and rely on feature detection instead. Browser detection is dangerous and error-prone.
  • Avoid using document.write.
  • Only run scripts on a page that are needed for that page.
  • Don't repeat yourself (i.e. keep your code DRY)
  • Do not modify JavaScript core objects .prototype unless you really know what you're doing.
  • Use method names that make sense, such as init() or setup() for code that starts things off. Be consistent on your project.
Inclusion of Code
[#] [Edit on Github]

Use external JavaScript files. Do NOT include JavaScript in-line in the page unless there is a good reason.

Use the <script></script> tag to include your JavaScript files at the bottom of your HTML document just before the closing </body> tag. For optimal page performance, concatenate your JavaScript into as few files as possible.

The only exception to script files being placed at the bottom of the document is Modernizr, which should be placed before the closing </head> tag on the document.

<script src="bundle.js"></script>
  • This should link to concatenated and minified, finalized JavaScript files.
  • Enable source maps to assist with debugging and testing.

In development environments, this may point at a non-optimized file, however having techniques in place to toggle optimized files on and off is often beneficial.

A reference similar to this may need to include a build-specific file name based upon a hash or something along those lines for HTTP cache purposes.

Learn more:

For information about build tools that help with these techniques, please see the Appendix.

Loading Files On Demand
[#] [Edit on Github]

On some sites it may be appropriate to load a single JavaScript file with all dependencies bundled together, or it may be more appropriate (such as in a very large SPA) to load files on demand, as they are needed, asynchronously.

BarkleyREI doesn not currently use asynchronous bundling methods to load JavaScript into the page.

Responsive Web Design

[#] [Edit on Github]

Responsive Web Design (RWD) is the term used for the practice of creating page layouts and user experiences that work on a variety of devices and screen sizes.

With the ever expanding mobile landscape and the evolution of the Internet of Things (IoT), the idea of a "standard" screen size has fallen by the wayside in favor of the rise of a device-agnostic approach. It is less and less common to launch two versions of a site, one for desktop and one for mobile.

To this end a series of techniques have been put together for pages to adjust based off browser's' current specs (e.g. width, height, pixel density, orientation, etc).

The techniques are referred to as Responsive Web Design (RWD) and it is another technique in the toolbox of progressive enhancement and adaptive web design.

Goals of Responsive Web Design

[#] [Edit on Github]

The goals of RWD are:

  • Offer an optimized user experience (UX),
  • regardless of the user's screen size or features supported on their device.

This is true whether it is a stadium jumbotron or the screen of a watch — and of course everything between.

Despite this lofty ideal, on Web projects the term "responsive web design" has generally been used in reference to an optimized experience for a set of target devices, usually:

  • A particular set of cell (smart) phones,
  • various tablets,
  • or desktop computer monitors (depending upon the target audience).

Typically reasonable effort is applied to accommodate the ideal UX for devices with screen sizes that fall outside of and in between.

Overall, critical content and features on a site should be:

  • Adjustable to different types of user interaction (e.g. click, swipe, pinch)
  • Realistically accessible based on the capabilities of different devices.

If meeting desktop browsers' feature sets and dealing with different platforms was difficult before, RWD introduces an almost infinite ecosystem of hardware and software that Web pages need to work on. The level of effort does often increase on projects featuring RWD.

Responsive Images

[#] [Edit on Github]

The picture element and img with srcset are valid standards now, and supported in many browsers. They can be freely pursued, though polyfills may be needed for some browsers.

You can read about this element and the evolution and standard at ResponsiveImages.org.

At this time, the <picture> tag is supported in most modern browsers, with additional support using the Picturefill polyfill.

Some basic rules to follow:

  • Always optimize your images using a tool such as Adobe Photoshop to assure you have the ideal image size and right amount of lossy compression.
  • Run all images though a lossless compressor like Compressor.io, Smush.it or ImageOptim (which has related tools also available as build-time scripts).

You can also consider “Compressive Images”, which are basically higher-resolution jpegs compressed at a higher percentage rate:

However, there are drawbacks:

  • The browser tends to use significantly more memory when storing and resizing these higher resolution images than scaling them to fit a container.

What's important to realize is that this is changing faster than we can develop. What you do now will be obsolete very soon, so be sure to stay on top of current trends.

Vector Graphics (SVG)

[#] [Edit on Github]

When working with an audience on unknown screen sizes and resolutions, as is the pretense in RWD, having graphics that can scale without degrading is a very appealing prospect. There are several vector implementation options.

Web fonts: Fonts are vectors. With the exposure of custom web fonts as part of the CSS level 2 specification, many developers have turned to custom font packages as a solution for icons and simple vectors.

  • Pros: this option allows for easy control of vector color, size and usage
  • Cons: all of the vectors single color and must be grouped others in one file.

SVG: SVG is an XML syntax for describing vector shapes.

  • Pros: vectors can be manipulated by CSS and/or JavaScript and allows for complex filters, animations and transitions.
  • Cons: SVG is only supported by IE9+

Grumpicon is a script that will detect SVG support and server the appropriate CSS (or needed fall back CSS code to assure compatibility.

Other Categories

[#] [Edit on Github]

Virtually everything can change when screen sizes change:

  • Grids
  • Typography
  • Accessible forms / validation messages
  • Main site navigation
  • Header or Footer content
  • In-page navigation, such as tabbed navigation, or accordions
  • Images
  • Data tables
  • Interactions and animations
  • Advertising types
  • Performance metrics

More thoughts and ideas: Multi-device Layout Patterns

Navigation Changes

[#] [Edit on Github]

Large horizontal navigation and mega-drop downs are not always practical on smaller screens. Frequently this means off-canvas navigation, collapsing menus into select boxes, or other approaches such as a full-screen overlay.

Progressive and Responsive Navigation is a great example of modifying the types of menu based on screen size.

Responsive Navigation Patterns and Complex Navigation Patterns

How navigation changes per screen size will depend entirely on the requirements and design for the project.

Next Steps & RWD Resources

[#] [Edit on Github]

Big collections:

Articles:

Blogs:


Getting Started with Mobile Development

[#] [Edit on Github]

As the name of RWD implies, it all starts with a flexible design that features components having mutable characteristics based on the available screen canvas and varied types of user interactions. Careful consideration needs to be taken when innovating to derive a design that can respond to various screens.

For a given project, always consider:

  • The extent of the use cases for each feature on the site.
  • The target audience and likelihood they may be using an alternative device to conduct certain activities on the site.
  • If all target devices will support all the technologies required.
  • That the UX will not be 100% the same across all devices, browsers and screens — nor should it be!
  • What happens to the design when the screen gets smaller and larger than the static canvas size it is being designed on.
  • For placement of content and decorative elements, are there patterns or rules that can describe where it falls and adjust with screen sizes?
  • Will some components be better suited as vector graphics (SVG or fonts) instead of raster files to allow for distortion free scaling?
  • Will assets need to be produced in different formats for different devices (e.g. HTML5 video, lower resolution artwork vs. high resolution artwork, smaller file sizes vs. larger sizes).
  • If a device offers a superior UX for some types of interaction (e.g. native date-pickers vs. traditional browser controls, or swiping instead of clicking on dots).
  • What happens when a feature is not supported by a device, or if a feature were to fail in a given device?
  • What if a device went off-line during usage of a feature?
  • The best ways to detect support for various features (e.g. Modernizr, etc.).

Brad Frost's Responsive Design Patterns and Responsive Design Resources are two great resources that continue to grow due to user contributions.

To Use a Prebuilt Grid Or Not?

[#] [Edit on Github]

Sometimes CSS grid frameworks are a good place to start ... but sometimes not.

They must match the design in terms of flexibility.

It's critical a developer learn the basics of how grid systems.

It may be beneficial to learn the coming Flexbox techniques as well.

While using a Framework isn't always the way to go, there is much to be learned from examining how they work and how they are put together.

BarkleyREI uses Foundation as a grid system, but it is not a requirement to build layout.

Progressive Enhancement

[#] [Edit on Github]

Since mobile phones and tablets are frequently the lower end in terms of capabilities, it is recommended to start with building the mobile experience first, and gradually add features. With this in mind, RWD could be considered a type of Progressive Enhancement, whereby users with basic devices can access basic content and features, however care is taken to layer on more sophisticated features for more powerful devices and desktop users.

With these techniques, users only get what their device or browser can handle, and feature detection can be used to add more features when appropriate — without breaking on less capable devices.

Responsive Design Best Practices

[#] [Edit on Github]

RWD is frequently said to be achieved through the use of:

  1. Percentage-based grids,
  2. flexible images that scale,
  3. and CSS media queries.

These are the core ideas behind RWD, though other techniques are often employed as the term grows in popularity and the use cases evolve.

Like all programming and creative processes there is flexibility in how you go about achieving these, so long as there is consistency within your team.

Some core guidelines:

  • Always design and develop the mobile UX first (thus start with small defaults and scale upwards; please see Mobile First)
  • Set the baseline Media Queries as a team for various types of devices, and try to stick to them as much as possible.
  • Add additional Media Queries — as necessary — for less than ideal experiences at the sizes in between, as appropriate for different types of content and components.
  • Build for speed (load time and interaction) and the minimum viable product for slower connection speeds and less able devices.
  • Be careful of images. Do not render a 5GB image at 100px by 100px. This does not change the bandwidth needed to download the file! Similarly if you are hiding an image with display: none, visibility: hidden or similar, the image may still be downloaded.
  • Test on real hardware. Actual testing on actual devices cannot be substituted with resizing a browser window, or even an "emulation" mode offered by a desktop browser.
  • A mobile browser is not a small desktop browser. Mobile versions of desktop browsers are frequently woefully different (or a totally different product) than their desktop counterparts, so do not assume that just because it works on Chrome desktop that it will work on an Android device.

Initial work, and first pass tests of media queries, may be performed in desktop browsers by resizing the screen or using a browser's developer tools that may feature an emulation mode (e.g. Chrome DevTools).

However, this is never a substitution for actual testing on actual devices with various Operating System versions.

Media Queries and CSS Breakpoints

[#] [Edit on Github]

Added as part of the CSS3 specification, media queries consist of a media type and at least one expression of a media feature (such as height, width and orientation) that describe the conditions under which a set of CSS rules apply.

For example:

@media screen (min-width: 300px) and (max-width: 800px) {
  .some-selector{
    /* CSS declarations go here */
  }
}

These widths are referred to as breakpoints as they are the point at which layout behavior breaks with the design at the prior size. This is typically screen size, and sometimes other conditions such as pixel density or even screen orientation (e.g. landscape or portrait; although this isn't that useful).

These are applied with CSS Media Queries test the device or browsers current feature set for various conditions and feature support. The most common example is screen size.

The golden rule is:

  • Don't specify vendor- or device-specific widths

Let the content and the design dictate the breakpoints.

  • For instance, targeting an ipad in portrait or an ipad landscape.
  • Popular devices will come and go and even within devices the specifications will change over time.
  • Avoid orientation/resolution based specifications in favor of width based ones (remember you are not targeting devices!).

Media Query Resources

A Device Agnostic Approach to Responsive Web Design is a great read on responsive techniques that do not favor one device over another, and are driven by content elements.

If you are placing breakpoints every 50-100px you are doing something wrong. While there is not a correct number of breakpoints there must be a balance between the control of the design and a manageable code base.

While working with media queries here are a few things to consider:

  • All modern browsers support CSS3 Media Queries (including browsers as far back as the stock Android 2.1 browser)
  • IE8 and below do not support Media Queries.
    • Respond.js (and similar JavaScript libraries) can be used to enable support for Media Queries in these older browsers (if needed).
    • Attempting to polyfill Media Query behavior in older browsers is usually not advisable. This is because the JS needed will cause an additional performance hit to the already slow JavaScript and rendering engine.

Instead, you are better off forcing older browsers to experience the site through a desktop experience (optionally tailored specifically for these older browsers).

  • This can be done either through feature detection (with the likes of Modernizr) or with IE conditional statements and optionally including additional CSS style sheets.

Notes:

Mobile First

[#] [Edit on Github]

The "Mobile First" techniques consider the lowest common denominator first, which is likely to be your mobile devices due to bandwidth limitations, loading times (not just screen size!), and even CPU speed of the devices.

Key considerations and techniques include:

  • Starting small, and work upwards. Use min-width, not max-width breakpoint definitions).
  • Begin with global content styles that apply across all breakpoints.
  • Next, add the styles that are seen below the smallest break point -- remember that using the min-width approach means that the "first breakpoint" will not be for small screens (like mobile size screens) but rather for larger ones (like mobile landscape or phablet size screens).
  • From here add additional styles at successive breakpoints using min-width media queries leveraging the CSS cascade to progressively add additional styles.
  • As the queries increase in minimum sizes, add the markup and styles necessary to lay components out differently on larger screens.
  • Examine site features for mobile-specific JavaScript events (e.g. touch, pointer, vs. mouse) and interactions (e.g. swipe).

Generally speaking smaller screen designs are a bit less complex (fewer images, effects, etc). Thus as the screens get larger the complexity tends to increase, conveniently lending to an additive approach to styling, very much in line with a mobile first pattern.

An example of working upwards in a CSS file might be:

/* GENERAL STYLES */
.example {...}

/* SECTION SPECIFIC STYLES - aimed at the smallest devices*/
.hero {...}

@media(min-width: 600px) {
  .hero {
    /* just the new stuff here, no need to be repetitive... */
  }
}

@media(min-width: 800px) {
  .hero {
    /* just the new stuff here, no need to be repetitive... */
  }
}

@media(min-width: 1400px) {
  .hero {
    /* might need larger font sizes at largest screen sizes */
  }
}

Note: the breakpoints specified above are not intended to be recommended breakpoints, but rather just illustrative of this general concept.

Another way of thinking about a mobile first pattern (from a design and development standpoint) is to:

  • Innovate for your smallest reasonable target device.
  • Then start "sizing your window up" until the user experience or the design degrades.
  • Add in a breakpoint and make some design modifications to fix the degradation.
  • Resume sizing up your view port until you reach a similar breakdown in design and repeat this exercise.

Recurse on this until you reach your largest reasonable target device - this is the mobile first pattern.

Speed is a feature

[#] [Edit on Github]

People expect page load time to be as fast if not faster on their mobile phones in comparison to a desktop experience.

  • Try to keep your Web site's footprint as small as possible (this is a general best practice).
  • Start with global styles that apply across all breakpoints
    • Optionally in-line these vital styles for faster initial render time
  • Consider every HTTP request
    • The request itself may end up taking as much if not more time then the transfer of the data and could block downstream actions or more vital downloads.
  • Concatenate, gzip and minified your production CSS/JS where possible as this will lower page load size and time
  • Load the least amount of JavaScript that is needed.
    • Wherever possible include script files at the end of your HTML document just before the </body> tag.

Advanced CSS3 techniques are easy to implement, but when you start combining them, rendering and scrolling performance can be affected.

Be careful of images!

  • Use a responsive image pattern that starts by serving a mobile optimized (and thus smaller file size) image first.

Appendix

[#] [Edit on Github]

Being a Front-end developer these days covers an enormous spectrum of technologies and techniques.

We hope to add more content, edit, and revise the content above with more information, samples, and resources.

Advanced Topics

On the Server

Front-end Developer Tool Chain | Workflow

CSS Preprocessors / Post-processors

Performance

Accessibility

Help and Reference

Additional Guides

CSS Guides
JavaScript Guides

Acknowledgments

[#] [Edit on Github]

And acknowledgments...

Dozens of folks have contributed to this guide either directly, through project experience, or have served as prior art that has inspired ideas in this document.

Special thanks to:

  • ISOBAR for inspiring this guide
  • Adam McIntyre
  • Addy Osmani
  • Brad Frost
  • Chris Coyier
  • Doug Crockford
  • Nicholas C. Zakas
  • Nicolas Gallagher
  • Nicole Sullivan
  • Paul Irish
  • Riccardo La Rosa
  • Rick Waldron
  • Rob Larsen
  • Tim Berners-Lee

All content licensed under Creative Commons Attribution 4.0 Unported License.

This document is based on the original by ISOBAR, 2015, and was modified by BarkleyREI, 2017