Modern front-end development
This post summarises what I would consider to be a base set of standards for modern front-end development. Over the last five years there has been a significant increase in the amount of tools, technologies and expertise in this field. I think it’s worth considering what is the minimum we should be doing to help us create good user interfaces that are usable, highly performant and easy to maintain and iterate on.
I’ve divided the post into five sections:
This section is about the broad approaches we should be taking when building websites, how we can speed up our development process and make our UIs easier to maintain.
Build websites responsively
We should create websites that adapt to any screen size. If you’re in need of convincing then Brad Frost’s This Is Responsive collection of resources does a good job of making the case for responsive web design (RWD) as well as how to actually do it!
RWD also has consequences for our workflow. As Andy Budd says in The Pastry Box:
Responsive design is an integrated process that requires designers and developers to work in harmony. It’s not a process that involves a designer mocking up 3 different versions of a page (small, medium and large) and then handing it over the wall to a developer.
We should make sure that whatever we build works in the least-capable browsers and only then add HTML5/CSS3 features for more advanced browsers. This means checking that our UI is functional in IE 6/7/8 or Android 2.3 (a browser matrix helps here) before adding these extra goodies.
The web is an open platform and the browser is a constantly evolving beast, therefore, we should strive to make our websites as accessible as possible.
User interfaces should be usable for people with disabilities. At the very least this should involve meeting some basic criteria such as the checklist provided by the A11Y project.
Think of a website in terms of modules rather than pages
Websites are made up of a number of different components. For example, the page you’re currently reading has a header, a blog post, a comments section and a footer. We can break some of these down even further: the blog post has a series of headings, paragraphs and lists.
When building websites we should encapsulate these components as modules that have a single responsibility, work as a stand-alone component and can be used with other modules to make up a web page. This is a much more effective way of building websites for the following reasons:
- Developers can work on different web page elements simultaneously without getting in each other’s way
- Existing page elements can be changed without worrying that this might break something else
- New page elements can be created quickly and easily
- Page elements can inherit from other elements
- UIs become more flexible since page elements can be easily included in different places without additional work
- Test for visual regressions using something like Wraith or PhantomCSS
- Test the behaviour of our websites with Selenium or PhantomJS
- Test the performance of our websites with, for example, YSlow for PhantomJS
In his post on “What makes a good engineering culture” Edmond Lau argues that organisations should “push relentlessly toward automation”. We need to automate many common and repetitive tasks preferably with Grunt and Bower. These include, but are not limited to, the following:
- Compiling CSS preprocessors
- Concatenating and minifying stylesheets and scripts
- Optimising images
- Generating documentation
- Enforcing code formatting rules
- Running tests
- Downloading and updating vendor libraries
- Generating boilerplate HTML, CSS and JS (Yeoman is good for this)
When writing this post I came across Addy Osmani’s presentation on “Automating Front-end Workflow” which discusses these things and other useful tools.
If we want to test and automate everything it’s important that this is done as part of a continuous integration process. Every time a developer commits new code all of the testing and automation tasks should be run and if anything fails the team needs to be alerted and deployments prevented.
Automatic browser reloads on save of a file
Don’t reinvent the wheel
Do not waste your clients’ or colleagues’ time coming up with your own CSS Reset (see Normalize), tabs (see jQuery UI), accordions (jQuery UI again) or DOM library (ever heard of jQuery?). There are many good solutions already out there for these kinds of problems so just use them!
Use semantic HTML
We should markup our content in a meaningful way using the latest HTML5 tags where applicable. This includes (but not limited to):
Favour default HTML5 behaviours over custom ones
Forms are a good example here. We can specify required fields, placeholder text and regular expressions to test against with HTML5. The
<datalist> element can help users autofill input elements.
Web components (in the near future)
Web components will become the default way for building websites in the not-too-distant future. It will help us build modules rather than pages (see above), provide encapsulation for our components and make the web platform more flexible. As soon as this feature has wide browser support we should use it immediately.
Architect our CSS
If we want to build modules rather than pages and make our modules easy to test we have to architect our CSS in a way that assists this process. We should decide on an approach for how we are going to write CSS that is enforced through linting, code reviews, automated checking or a combination of these methods. My preference is to follow an OOCSS approach using something like SUIT.
Even if you don’t want to use OOCSS it’s very important that conventions are laid down for writing CSS. Without this our websites will become harder to develop for and iterate on and building new features can cause regressions in other areas of the site.
Lint our CSS
To help enforce an approach to writing CSS use something like CSSLint.
In order to keep code DRY and user interface components consistent using something like CSSCSS can be very helpful.
Use CSS3 (especially for animations)
Using something like LESS, SASS or Stylus helps us keep our code DRY, encourages re-use of CSS and helps to take away some of the pain points of developing for the browser such as dealing with vendor prefixes. Even simple preprocessing such as vendor prefix generation and enabling use of CSS variables (an approach taken by Twitter) should be part of our workflow.
Flexbox (in the near future)
Flexbox solves many of the common layout issues front-end developers face such as vertical centering, equal height columns and simple grids. It’s supported in all modern browsers so we’re just waiting for a few stragglers such as IE8 to die out before it will be a staple of front-end development.
Use a module loader
Consider using an MVC framework for more “app-like” experiences
In order to deliver good experiences we need to make sure our websites load quickly and work smoothly. This section discusses some things we can do to improve performance.
Do the basics
All front-end developers should know that every extra http request on a page and every additional kilobyte downloaded hurts performance. We should always do the basics:
- Optimise images
- Sprite background images
- Use gzip
- Cache resources
- Put scripts at the bottom of the page
- Serve appropriate images based on the user’s screen size
There is a lot more we can do but these are simple things that improve download time. I would recommend looking at the Google pagespeed module for Apache and Nginx that talks about additional performance improvements we can make and automates many of these things for us.
Minimise browser painting and reflow
Good UIs are smooth, pleasant to use and avoid jank. One of the most expensive operations a browser can perform is rendering new DOM elements and recalculating the position of existing elements. We can minimise these operations by, for example, adding new elements to a page in a batch rather than one at a time. When moving elements we can ensure that they are positioned in such a way that they do not affect the layout of other elements.
Use hardware-accelerated animations (especially for mobile)
With CSS3 Transforms we can use hardware-accelerated animations. This is particularly important for mobile devices where animations can feel very sluggish depending on which properties we’re animating. The only properties that benefit from hardware-acceleration are the following:
We should aim to only use animations with these properties. Of course animating things like width and height forces recalculations of the elements around them and these are expensive for the browser.
In this post I’ve summarised how I feel front-end developers should be working today. I think following these practices facilitates building good user interfaces that are enjoyable to use and easy to maintain.