CSS Styleguide - HelixDesignSystem/helix-ui GitHub Wiki

!! IN PROGRESS !!

Quick Reference

REQUIRED

  1. Spaces, not tabs
  2. Two (2) spaces per indent
  3. Unix line breaks (\n)
  4. Max line length: 120
  5. Always double-quote strings
  6. Anything that can be quoted should be quoted
  7. Always write case-insensitive syntax in lowercase
    • selectors, declarations, keywords, hex colors, units, etc.
  8. No inline blocks
    1. Open block on same line as the last selector
    2. Close block on line after last declaration
  9. One (1) declaration/rule per line
    • Never on the same line as a selector
  10. One (1) selector per line
  11. Exclude unit for 0 values
  12. Always prefix helper classes with hx using hxLowerCamelCase notation
  13. One (1) space after colon (no space before)
  14. One (1) space after comma (no space before)
  15. No trailing space at end of lines
  16. Always include final newline at end of source
  17. Never begin source files with a blank line

Recommended

  1. Alphabetize declarations within each block
  2. Avoid inlining multiple selectors in a selector list
  3. Arrange @import statements before all other content in generated CSS
  4. Use shorthand properties with caution

Standards

Colon Spacing

  1. no space before colon
  2. one (1) space after colon

Example:

/* PASS */
@media (min-width: 900px) { }
:root {
    --hxCustom-prop1: foobar;
    font-size: 16px;
}

/* FAIL */
@media (min-width:900px) { }
@media (min-width :900px) { }
@media (min-width : 900px) { }
:root {
    --hxCustom-prop1:foobar;
    --hxCustom-prop2 :foobar;
    --hxCustom-prop3 : foobar;
    font-size:16px;
    font-size :16px;
    font-size : 16px;
}

Operator Spacing

  1. one (1) space before operator
  2. one (1) space after operator
  3. Attribute selector operators should never have space around them

Example:

/* PASS */
@media (width >= 600px) { }
input[type="number"] { }

/* FAIL */
@media (width>=600px) { }
@media (width >=600px) { }
@media (width>= 600px) { }

input[type= "number"] { }
input[type ="number"] { }
input[type = "number"] { }

List Spacing

  1. no space before comma
  2. one (1) space after comma

Example:

/* PASS */
.foo {
    background-image: linear-gradient(90deg, transparent, #ffffff);
}

/* FAIL */
.foo {
    background-image: linear-gradient(90deg,transparent,#ffffff);
    background-image: linear-gradient(90deg ,transparent ,#ffffff);
    background-image: linear-gradient(90deg , transparent , #ffffff);
}

Quotes and Strings

  1. All quoted values should use double-quotes
  2. Anything that can be quoted should be quoted
    • e.g., url() paths, attribute selector values, non-keyword font families, etc.
  3. Strings should never be multi-line

Example:

/* PASS */
@import url("https://example.com/styles.css");
input[type="number"] { 
    font-family: "Helvetica", sans-serif;
}
.foobar::before {
  content: "Foobar: ";
}

/* FAIL - no quotes */
@import url(https://example.com/styles.css);
input[type=number] {
    font-family: Helvetica, sans-serif;
}
.foobar {
    grid-template-areas: foo bar;
}
.foobar::before {
  content: Foobar: ;
}

/* FAIL - wrong quotes */
@import url('https://example.com/styles.css');
input[type='number'] {
    font-family: 'Helvetica', sans-serif;
}
.foobar {
    grid-template-areas: 'foo' 'bar';
}
.foobar::before {
  content: 'Foobar: ';
}

/* FAIL - multi-line string */
.foobar::before {
  content: "Foo\nBar:";
}

@keyframes

  1. do not use !important within keyframes
    • restricts reuse
    • not supported in all browsers
    • can result in unexpected behavior
  2. prefix keyframe names with hx-
    • avoids conflicts with 3rd-party styles

Example:

/* PASS */
@keyframes hx-spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

/* FAIL */
@keyframes spin {
  0% {
    transform: rotate(0deg) !important;
  }
  100% {
    transform: rotate(360deg) !important;
  }
}

@media Queries

  1. do not use max-width in media queries
    • encourages mobile-first development
  2. do not use vendor-prefixed features
    • prevents incompatibilities from browser updates

Custom Properties

(a.k.a. CSS Variables) Not all browsers support custom properties, so you'll need to make sure you have a fallback property for legacy browsers.

IE Edge Chrome Safari Firefox Opera
n/a 15+ 49+ 9.1+ 31+ 36+
.hxFoobar {
  /* Fallback Styles (legacy browsers) */
  background-color: gray;

  /* Modern Styles (modern browsers) */
  /* overrides above, legacy browsers ignore it */
  background-color: var(--background-color, gray);
}

Alternatively, you could start with the fallback and use a @supports query to apply CSS Custom Properties. (The custom property and value used in the query just needs to be valid CSS and doesn't need to match the exact custom property and value.)

/* Fallback Styles */
.hxFoobar {
  background-color: gray;
}

/* Modern Styles */
@supports (--modern: true) {
  .hxFoobar {
    background-color: var(--background-color, gray);
  }
}

Numbers

  1. Exclude leading zeros
  2. Exclude trailing zeros
  3. Maximum precision in the thousandths
    • Pass: 1.125em
    • Fail: 1.1245em

Blacklisted Units

The following units are blacklisted and shouldn't be used.

  • cm
  • ex
  • in
  • mm
  • pc
  • pt

Best Practices

The following guidelines are not required but are highly recommended.

Use Shorthand Properties with Caution

Although CSS shorthand properties are useful to reduce the size of compiled assets, related properties may get defaulted to a value that is undesirable.

  • Shorthands have long effects
  • Double-check expanded properties being set by CSS shorthand
    • background: lime; isn't the same as background-color: lime;