Malcolm 'Max' DeRungs

CSS / LESS / SCSS

Conventions

  • Create and extend CSS files following global patterns. Minimize customization, as features are rarely styled in isolation.
  • Avoid descendant selectors (i.e. don’t use .sidebar h3).
  • Avoid IDs as styling hooks.
  • Avoid attaching classes to elements (i.e. don’t do div.header or h1.title).
  • Avoid using !important, except in rare cases.
  • Use a LESS / SCSS compiler for readability. CSS-in-JS is popular, but not as useful in Agile teams with only basic CSS skill sets.
  • Use shorthand properties everywhere (i.e. border: 1px solid red)
  • Always specify margin and padding as complete selector sets (i.e. use margin: 1rem 0 0 0 to specify top margin rather than margin-top: 1rem)

Files

Aim for the smallest CSS footprints by organizing LESS / SCSS styles into separate files that can be imported selectively for each view as needed.

Order styles from general to specific. The last selector wins.

Variables

Repeating elements are good candidates for turning into variables:

  • @media breakpoints
  • color
  • border and border-radius
  • box-shadow
  • @font-face

Declaration Order

Order declarations alphabetically under selectors (they're easier to maintain that way).

.site-header {
    align-items: center;
    border-bottom: 1px solid var(--color-border);
    display: flex;
    justify-content: flex-start;
    opacity: 1;
    padding: .5rem 2rem;
    top: 0px;
    visibility: visible;
    width: 100%;
    z-index: 100;
}

Selector Names

  • Use names to describe a feature or function better than or in place of a comment (i.e. .site-header-mobile).
  • Classes - use all lowercase (i.e. .site-header-mobile, .site-header-desktop, site-header-mobile-dropdown)
  • IDs - begin each word with uppercase (i.e. Modal-Dialog-Open-Click-21)
  • Separate each word with a dash (easier to doubleclick and replace individual words). Avoid underscores.
  • Name and collect selectors into the features or components they describe (i.e. .site-header-mobile-dropdown). Avoid one-offs.

Order words to create a visual hierarchy, like:
.site-header-mobile-wrapper
.site-header-mobile
.site-header-mobile-dropdown
.site-header-mobile-dropdown-left
.site-header-mobile-dropdown-right

Units

Use rem instead of px units for sizing. This helps the UI scale proportionally when the browzer zooms. Set the rem base scale globally by specifying a font-size in the <html> and/or <body> element.

Set this font-size to ten pixels so rem units can be readily be calculated as multiples of ten. For example: 10px = 1rem, 16px = 1.6rem, 250px = 25rem, 599px = 59.9rem ... and so on.

html,
body {
    font-size: 10px;
}

Breakpoints

Write base styles for mobile devices first and override them with breakpoint media queries for progressively larger displays.

Spec breakpoints that fall between the widths of major display types. The combination of max and min width breakpoints approach makes working with phones easier.

@media (max-width: 59.9rem) {}
@media (min-width: 60rem) {}
@media (min-width: 90rem) {}
@media (min-width: 120rem) {}
@media (min-width: 180rem) {}

Variable names can help implementation.

@phone: ~"screen and (max-width: 599px)";
@tablet: ~"screen and (min-width: 600px)";
@desktop: ~"screen and (min-width: 900px)";
@widescreen: ~"screen and (min-width: 1200px)";
@superwide: ~"screen and (min-width: 1800px)";

More expressive variable names are better.

@mixin for-phone-only {
    @media (max-width: 59.9rem) {
        @content;
    }
}

@mixin for-tablet-portrait-up {
    @media (min-width: 60rem) {
        @content;
    }
}

@mixin for-tablet-landscape-up {
    @media (min-width: 90rem) {
        @content;
    }
}

@mixin for-desktop-up {
    @media (min-width: 120rem) {
        @content;
    }
}

@mixin for-big-desktop-up {
    @media (min-width: 180rem) {
        @content;
    }
}

Position media queries so they are close the base styles they modify.

.site-menu-desktop {
    display: none;
}

@media (min-width: 600px) {
    .site-menu-desktop {
        display: initial;
    }
}

Or

.site-menu-desktop {
    display: none;

    @media (min-width: 600px) {
        display: initial;
    }
}

Fonts

Font Families

Favorite web font families for code are sans-serif => Poppins, Montserrat, Whitney SSm, Avenir, and Barlow.

Font Scale

Th a typographic scale for font sizing based on classic proportions like 1:2, 2:3, 2:5, 5:8, etc.

Note: a Minor Third scale can accomodate up to five header sizes. Most sites only need three.

Font Weight

Colors

Using Hex instead of HSL is usually easier for others on the team edit and maintain. Keep the byte count low by using the three-digit shorthand syntax.

$color-black: #333;
$color-gray: #999;
$color-green: #70bf63;
$color-lightgray: #d4d4d4;
$color-red: #ff0000;
$color-white: #fff;

$color-background-darkgray: #e7e7e7;
$color-background-gray: #f7f7f7;
$color-background-panel: #007bff12;
$color-border-dark: #b4b4b4;
$color-border-light: #d4d4d4;
$color-border-primary-action: #007a87;
$color-border-secondary-action: #b4b4b4;
$color-button-primary-action: #007a87;
$color-button-secondary-action: #707070;
$color-button-disabled: #e7e7e7;
$color-global-navbar: #1063b7;
$color-global-navbar-active: #0c4a88;
$color-icon: #007a87;
$color-link: #007a87;
$color-link-selected: #595959;

Using HSL allows for more programmatic color control.

// Primary hues
@hueR: 10;
@hueO: 29;
@hueY: 42;
@hueG: 111.7;
@hueB: 210;
@hue0: 0;

// Theme color mix
@color-blu: hsl(@hueB, 84%, 39%);
@color-yel: hsl(@hueY, 95%, 63%);
@color-orn: hsl(@hueO, 86.5%, 59%);
@color-grn: lighten(hsl(@hueG, 42%, 42%),15%);
@color-red: lighten(hsl(@hueR, 100%, 50%), 25%);

// Base color variables
@color-background: hsl(@hue0, 0%, 97%); //#F7F7F7
@color-blu-light: lighten(@color-blu, 10%);
@color-blu-dark: darken(@color-blu, 10%);
@color-nav: @color-blu;
@color-nav-active: darken(@color-blu, 10%);
@color-link: lighten(@color-blu, 10%);
@color-icon: lighten(@color-blu, 20%);

Keep colors global where possible for repeatability across products.

/* set defaults to 'light' prior to choice of background */
:root body {
  --color-background-code: #e1e8ed;
  --color-background-primary: hsla(40, 95%, 100%, 1);
  --color-background-secondary: hsla(40, 95%, 99%, 1);
  --color-background-tertiary: hsla(220, 5%, 90%, 1);
  --color-border: #ccc;
  --color-border-hover: #666;
  --color-font-code: hsla(220, 5%, 20%, 1);
  --color-font: hsla(220, 0, 0, 1);
  --color-font-headers: hsla(220, 5%, 5%, 1);
  --color-font-hover: hsla(40, 5%, 70%, 1);
}

body.light {
  --color-background-code: #e1e8ed;
  --color-background-primary: hsla(40, 95%, 100%, 1);
  --color-background-secondary: hsla(40, 95%, 99%, 1);
  --color-background-tertiary: hsla(220, 5%, 90%, 1);
  --color-border: #ccc;
  --color-border-hover: #666;
  --color-font-code: hsla(220, 5%, 20%, 1);
  --color-font: hsla(220, 0, 0, 1);
  --color-font-headers: hsla(220, 5%, 5%, 1);
  --color-font-hover: hsla(40, 5%, 70%, 1);
}

body.dark {
  --color-background-code: #293742;
  --color-background-primary: hsla(220, 5%, 15%, 1);
  --color-background-secondary: hsla(220, 5%, 10%, 1);
  --color-background-tertiary: hsla(40, 5%, 80%, 1);
  --color-background-featured: hsla(0, 5%, 15%, 1);
  --color-border: #666;
  --color-border-hover: #ccc;
  --color-font-code: hsla(40, 5%, 90%, 1);
  --color-font: hsla(40, 5%, 95%, 1);
  --color-font-headers: hsla(40, 5%, 100%, 1);
  --color-font-hover: hsla(220, 5%, 30%, 1);
}
Color Functions
color: color(var(--color-background-primary) l(-10%));

Icons

Font icons like IcoMoon (with the online IcoMoon App) can consume less memory than PNG and JPG sprites. These icon sets can also be versioned.

@import "icomoon-variables.less";

@font-face {
    font-display: block;
    font-family: '@{icomoon-font-family}';
    font-style: normal;
    font-weight: normal;
    src: local('☺'),
    url('@{icomoon-font-path}/@{icomoon-font-family}.ttf?@{icomoon-version}') format('truetype'),
    url('@{icomoon-font-path}/@{icomoon-font-family}.woff?@{icomoon-version}') format('woff'),
    url('@{icomoon-font-path}/@{icomoon-font-family}.svg?@{icomoon-version}#@{icomoon-font-family}') format('svg');
}

// declare IcoMoon vector font icons globally
[class^="icomoon-"],
[class*="icomoon-"] {
    .font-light();
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    &:before,
    &:after {
        font-family: '@{icomoon-font-family}' !important;
        text-decoration: none !important;
    }
}

Use named wrapper (container) and block classes to shape w/ width, height, overflow around base class elements.

.thisthat-wrapper {
	display: flex;
	margin: 0 auto; 
	
	.thisthat-block {
		color: red;
		
		.this {
			font-size:  1rem;
		}
		
		.that {
			font-size: .5rem;
		}
	}
}

External References

Architectures
Object Oriented CSS (OOCSS)
Scalable and Modular Architecture for CSS (SMACSS)

Frameworks

Concepts

Colors