# CSS Design Patterns

## Summary


To become a good web designer/developer, it's not enough to know CSS properties and their values. We need to know the contexts in which each property-value pair is applicable, how results differ in different contexts, and how various properties interact. Rather than memorize hundreds of rules and their exceptions, it's more efficient to get familiar with contexts of usage and combinations of properties applicable in those contexts. This is what CSS design patterns is all about. 

Design patterns are common in programming, such as in object-oriented programming. In HTML/CSS, design patterns are those that work across browsers and devices. They manage complexity, mitigate code bloat, and improve productivity. They're the building blocks that facilitate the creative process: the designer picks known patterns, adjusts them to current context and combines them for a final result.

## Discussion

### What are the design patterns pertaining to the CSS Box Model?

Common ways to display an element are `inline`, `inline-block` and `block`. Special ways include `list-item` and `table`. We can also take out an element from its normal flow using CSS properties `position` and `float`. More sophisticated ways to layout elements include CSS Flexbox, CSS Grid, and CSS Multi-column. 

Bowers et al. talk about three patterns that affect box dimensions: 

    + **Sizing**: manually assign absolute or relative sizes
    + **Shrinkwrapping**: shrink to fit the content
    + **Stretching**: stretch to fill its parent containerThese can be combined with positioning patterns **indenting**, **offsetting**, and **aligning**. Specifically, a stretched element can be indented and this affects its dimensions. A sized or shrinkwrapped element can be offset or aligned without affecting its dimensions. 

Much of this is achieved by applying CSS rules to parent and grandparent containers of the element. These rules mainly specify dimensional properties, positional properties and margins. 


### What are some traditional CSS patterns for layout design?

Two patterns are not recommended: fixed-width layouts since measurements are absolute and tables since table cells "can't flow" when viewport changes. 

One design pattern is to use columns whose widths adjust to viewport width. On smaller screens, columns reflow into rows. This is called **fluid layout** and is achieved using properties `float`, `width`, `min-width` and `max-width`. 

In **elastic layout**, overall width is set relative to some design element such as font size. A **hybrid layout** is a combination fixed and fluid/elastic layouts. 

Property `width` is actually an element's inner width. Sometimes we wish to fix the outer width in design and then adjust the margin, border and padding without affecting the layout. This is possible by having an element within another element, called **outside-in** pattern. The inner element includes margin, border and padding but the outer element has none. 

In fluid layouts, mixing fixed values and percentages is not ideal but can't be avoided. Using percentages isn't possible for borders. It's common to use fixed values for margins and padding, and percentages for width. This problem is solved by the outside-in pattern. 


### What responsive layout patterns are possible with CSS Flexbox and CSS Grid?

In 2019, LePage used Flexbox and media queries to implement five layout patterns: 

    + **Mostly Fluid**: On small screens, content reflows and columns stack vertically. On bigger screens, margins are adjusted.
    + **Column Drop**: Columns stack vertically on smaller screens.
    + **Layout Shifter**: Content moves around when screen sizes change. Most responsive with many breakpoints but also more complex to maintain.
    + **Tiny Tweaks**: Only small changes involving font sizes, image dimensions, or content offsets.
    + **Off Canvas**: On smaller screens, less frequently used content is kept off-screen but accessible with a single click.Rachel Andrew has shared a number of patterns based on CSS Grid. Typical layouts contain header, footer, sidebar and main content area. An example of nested grid shows positioning of media along with text and caption. She also gives examples of using named lines and areas that are easer for developers to work with. Bryan Robinson has shared a good example of a responsive layout with CSS Grid. 


### What CSS design patterns help control spaces?

CSS gives designers plenty of options to control spaces. Margin adds space on the outside of an element. Padding adds space between the element's border and its content. For both of these, each boundary (top, right, bottom, left) can be individually set. Negative margins can remove spaces and cause elements to overlap. 

In the flow of text, spacing can be controlled with `letter-spacing`, `word-spacing`, `line-height`, and `text-indent`. In addition, `text-align:justify` will stretch out inter-word spaces. Property `text-indent` doesn't work on inline elements. For hanging indent, we can use negative `text-indent` and positive `padding-left`. 

Whitespace can be preserved with `white-space:pre`, which is useful for displaying code snippets in monospaced font. To preserve whitespace and also wrap long lines, use `white-space:pre-wrap`, `white-space:pre-line`, or `white-space:break-spaces`. In addition, `word-break:break-all` and `word-break:break-word` give more control. 


### Which are the different categories of CSS design elements?

Sometimes it's helpful to think of CSS design patterns in terms of UI components or widgets. A typical webpage has header, footer, menu, buttons, breadcrumbs, forms, tables, pagination, etc. Common ways of using CSS for these purposes can be gathered into CSS patterns. 

The page UI Patterns on CodePen documents many such patterns, although some of them are not pure CSS (they include JavaScript as well). 

Phuoc's CSS Layout is another place for CSS patterns. Close to 100 patterns are featured here under the categories of layout, navigation, input, display, and feedback. 


### Is it a good idea to adopt a CSS framework?

**CSS frameworks** offer a faster route to benefit from CSS design patterns. Such frameworks often provide many patterns that can be mixed and matched to achieve an intended design. They save us the effort of hand-coding dozens of rules. Well-known frameworks include Bootstrap, Foundation, Bulma, UIkit, Semantic UI, Susy, Materialize, Pure, Skeleton, and Milligram. 

Some prefer to choose a small lightweight framework rather than one that tries to do too many things. Smaller frameworks and libraries may also be easier to customize. In any case, be wary of frameworks in which abstractions leak. Some lightweight frameworks include Pure, Milligram, Picnic, Wing, and Chota. 

**CSS preprocessors** are also useful in managing the complexity of CSS styles. Features include variables, nesting, mixins, functions and mathematical operations. Well-known preprocessors include Sass, LESS and Stylus. These can be compiled into CSS. In fact, many CSS frameworks make use of preprocessors. 

Even when CSS preprocessors are used, developers can't sacrifice a solid understanding of CSS. Preprocessors complement CSS, not replace it. 


### What are some CSS anti-patterns that I should avoid?

We note a few CSS anti-patterns: 

    + **Undoing Styles**: Use of `float:none`, `padding:0`, or `border-bottom:0` are examples where we're attempting to undo styles set elsewhere. It shows that we added styles too early.
    + **Magic/Hard-coded Numbers**: These make the design brittle to changes and confusing for other developers. Examples, `top:37px` or `line-height:32px`. The latter could be made relative, such as `line-height:1.5em`.
    + **Qualified Selectors**: Selector `ul.nav` means that style can't be reused for navigation menus on other element names. Selector `.nav` is more reusable. On the flip side, we could have selectors that are too broad, such as `ul`. Instead, prefer a class selector.
    + **Loose Class Names**: Selector `.card` doesn't suggest its intended purpose. Instead, `.credit-card-image` is better. Another poorly named selector is `.teal`. It describes a visual attribute and has no semantic value.
    + **Repetitive Key Selectors**: Same key selector appearing in many CSS rules suggests poor design. There's no single source of truth. Instead, use BEM convention.
    + **Complex Rules**: A rule such as `.slider {height:27px; float:left;}` is trying to do too many things. Instead, we could break it up into two separate rules `.slider` and `.left`.


## Milestones

1997

At a workshop, Jenifer Tidwell presents *Common Ground*, a pattern language for human-computer interface design. She later develops this work and publishes it as a book titled *Designing Interfaces* in 2005. This is just an example to highlight that CSS design patterns are related to **UI patterns**. 

2001

A simple three-column layout with a top header that works for all browsers is surprising difficult to design. Owen Briggs builds such a layout and shares his styles online under the title *Box Lessons*. In time, this becomes a useful reference for many CSS developers. This is an early example of CSS design patterns. 

Dec  
2005

Holzschlag writes about the constraints of table-based layouts. She proposes the use of CSS to create more flexible layouts. CSS enables designers design for discrete, semantic elements rather than be limited to grid designs. 

Oct  
2006

As a CSS preprocessor, **Sass** v0.1.0 is released to help developers manage complex styles. Subsequently, other preprocessors are released: LESS v1.0 (Apr 2010) and Stylus v0.02 (Jan 2011). Adoption of preprocessors grows through the 2010s. A survey from 2016 reveals that about 86% of respondents use a CSS preprocessor in their development workflow. 

Mar  
2009

Marcotte proposes **Fluid Grids** as a layout pattern in which all design elements are sized in proportion to font size. This overcomes the assumption of "minimum screen resolution" and creating fixed layouts. In later years, this is called **elastic layout**. 

Aug  
2011

Twitter open sources **Bootstrap**, what's possibly the world's first framework for frontend design. For pragmatic developers who wish to get things done, patterns in Bootstrap speed up development. Subsequently, Bootstrap 2 (Jan 2012) adds responsive functionality, Bootstrap 3 (Aug 2013) becomes responsive by default and mobile first, Bootstrap 4 (Jan 2018) moves from LESS to Sass and uses CSS Flexbox, and Bootstrap 5 Alpha (Jun 2020) replaces jQuery with vanilla JS and card decks with CSS Grid.  

2011

Bowers et al. publish the book *Pro HTML5 and CSS3 Design Patterns*. They describe more than 350 design patterns, each pattern being modular, customizable, and reusable. Patterns come with working code in HTML and CSS. 

Mar  
2012

Based on a study of layout examples on Media Queries website, Wroblewski identifies five high-level patterns: Mostly Fluid, Column Drop, Layout Shifter, Tiny Tweaks, and Off Canvas. Years later, in 2019, LePage showcases how these patterns can be implemented using CSS Flexbox and media queries. 

Sep  
2012

W3C publishes the first Candidate Recommendation of **CSS Flexible Box Layout Module** (first draft in 2009). In May 2017, W3C publishes **CSS Grid Layout Module Level 1** as a Candidate Recommendation (first draft in 2012). Both Flexbox and Grid greatly simplify CSS rules for layouts. In time, developers share patterns for these two approaches.  

Sep  
2018

Bob Myers argues that BEM, CSS preprocessors, CSS frameworks, and obsessive separation of content and presentation are all CSS anti-patterns. CSS engines are faster today than when BEM came out. Preprocessors complicate build pipelines and require developers learn their syntax. Frameworks such as Bootstrap are not needed now for layout when we have CSS Flexbox and CSS Grid.