MercadoLibre CSS Style Guide
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.editorconfig
.gitattributes Add whitespace normalization Aug 25, 2016
.gitignore
.npmrc
.sasslintrc
license
package.json
readme.md

readme.md

CSS Style Guide

Mercado Libre CSS Style Guide.

Table of contents

  1. Introduction
  2. Language
  3. Whitespace
  4. Rules
  5. Declarations
  6. Selectors
  7. Properties and values
  8. At-rules
  9. Comments
  10. Appendix: Sass
  11. Appendix: Vendor prefixes
  12. Appendix: Linter

Introduction

This document defines formatting rules and methods for writing stylesheets. It aims at helping you to author code that is readable, maintainable, reusable and scalable.

By following this guidelines we are going to:

  • Improve code quality.
  • Encourage collaboration.
  • Reduce time required to understand existing code.
  • Increase productivity.
  • Maintain our sanity.

It’s very important to keep in mind that:

  • Consistency is fundamental. Every line of code should appear to be written by a single person, no matter the number of contributors and their personal preferences.

  • Code must be focused on readability and simplicity —even at the cost of repetition. Clever code that is hard to understand usually does more harm than good.

This guidelines should be learned, understood, and followed at all times. Any deviation must be fully justified.

Language

Always write in English: comments, class names, etc. Remember that we are a multicultural company and not all of us speak the same language.

Whitespace

  • Use Unix newline character: LF.
  • Use two spaces per indentation level.
  • Remove all trailing whitespace.
  • Always end files with a newline.
  • Use only one blank line as a separator.
/* DON'T */

.foo {¤
——··font-weight: 900;¤
——color: #222;····¤¬
}——¤¬
/* DO */

.foo {¬
··font-weight: 900;¬
··color: #222;¬
}¬
¬

Make this easier by using this configuration for EditorConfig. If you want to understand why whitespace it’s important you can check this presentation.

Rules

  • Place the opening brace next to the selector.
  • Use one space before the opening brace.
  • Place the closing brace in the same column as the first character of a rule.
  • Separate each rule by a blank line.
/* DON'T */

.foo
{
  color: #222;
}
.bar{color: #999;}
/* DO */

.foo {
  color: #222;
}

.bar {
  color: #999;
}

In large blocks of rules that only consist of one selector and one declaration, a single-line format should be used.

  • Use one space after the opening brace.
  • Use one space before the closing brace.
  • Don’t separate rules by a blank line.
  • Don’t align braces.
/* DON'T */

.foo{color: #000;}
.foobar {color: #222;}

.bar    { color: #444; }
.barfoo { color: #666; }
/* DO */

.foo { color: #000; }
.foobar { color: #222; }
.bar { color: #444; }
.barfoo { color: #666; }

Don’t indent rules with the intention to replicate the DOM structure. This will make your code less flexible and introduce a maintenance burden.

/* DON'T */

.foo {
  color: #222;
}

  .foo__bar {
    color: #444;
  }

    .foo__baz {
      color: #666;
    }
/* DO */

.foo {
  color: #222;
}

.foo__bar {
  color: #444;
}

.foo__baz {
  color: #666;
}

Declarations

  • Define one declaration per line.
  • Place one space after the colon.
  • Always end declarations with a semicolon.
  • Don’t place spaces before the colon or the semicolon.
/* DON'T */

.foo {
  font-weight:900;
  color : #222 ;
}

.bar {
  padding:10px; margin:0
}
/* DO */

.foo {
  font-weight: 900;
  color: #222;
}

.bar {
  padding: 10px;
  margin: 0;
}

Selectors

  • Place one selector per line in grouped selectors.
  • Quote attribute values using single quotes.
/* DON'T */

.foo, .bar {
  color: #222;
}

.foobar[attr=val] {
  color: #444;
}
/* DO */

.foo,
.bar {
  color: #222;
}

.foobar[attr='val'] {
  color: #444;
}

Recommendations

Never use id selectors.

/* DON'T */

#foo {
  color: #222;
}
/* DO */

.foo {
  color: #222;
}

Avoid type selectors as much as you can.

/* DON'T */

.foo h1 {
  color: #222;
}
/* DO */

.foo-heading {
  color: #222;
}

Properties and values

Don’t specify length units for zero values.

/* DON'T */

.foo {
  padding: 0px 20px;
}
/* DO */

.foo {
  padding: 0 20px;
}

Always specify leading zeros in fractional numbers.

/* DON'T */

.foo {
  top: .25%;
  left: -.5%;
}
/* DO */

.foo {
  top: 0.25%;
  left: -0.5%;
}

Use lowercase for hexadecimal values, and shorthand notation when allowed.

/* DON'T */

.foo {
  background: #ffffff;
  border-color: #F3F3F3;
}
/* DO */

.foo {
  background: #fff;
  border-color: #f3f3f3;
}

Quote URL values using single quotes.

/* DON'T */

.foo {
  background: url(../images/image.png);
}
/* DO */

.foo {
  background: url('../images/foobar.png');
}

Quote font family names that contain whitespace using single quotes.

/* DON'T */

.foo {
  font-family: "Times New Roman", Times, serif;
}
/* DO */

.foo {
  font-family: 'Times New Roman', Times, serif;
}

Don’t place spaces before the opening parenthesis nor after the closing parenthesis of a function.

/* DON'T */

.foo {
  width: calc( 20% - 5px );
  background: rgba( 0, 0, 0, 0.6 );
}
/* DO */

.foo {
  width: calc(20% - 5px);
  background: rgba(0, 0, 0, 0.6);
}

Include a space after each comma in comma-separated values.

/* DON'T */

.foo {
  font-family: 'Times New Roman',Times,serif;
  background: rgba(0,0,0,0.6);
}
/* DO */

.foo {
  font-family: 'Times New Roman', Times, serif;
  background: rgba(0, 0, 0, 0.6);
}

Long comma-separated set of values should be arranged across multiple lines.

  • Place the first set in the same line than the property.
  • Place the following set/s in a new line using one extra level of indentation.
/* DON'T */

.foo {
  box-shadow: inset 0 0 4px rgba(17, 17, 17, 0.6), 0 0 8px rgba(0, 0, 0, 0.6);
  background: url('../images/foobar.png') repeat-y,
  url('../images/barfoo.png') repeat-x;
}
/* DO */

.foo {
  box-shadow: inset 0 0 4px rgba(17, 17, 17, 0.6),
    0 0 8px rgba(0, 0, 0, 0.6);
  background: url('../images/foobar.png') repeat-y,
    url('../images/barfoo.png') repeat-x;
}

Recommendations

When possible, use shorthand properties.

/* DON'T */

.foo {
  padding-top: 0;
  padding-right: 10px;
  padding-bottom: 20px;
  padding-left: 10px;
}
/* DO */

.foo {
  padding: 0 10px 20px;
}

Don’t use keyword values when the same result could be achieved using an explicit value.

/* DON'T */

.foo {
  background: white;
  border-width: medium;
}
/* DO */

.foo {
  background: #fff;
  border-width: 4px;
}

Never use !important to resolve a specificity issue.

/* DON'T */

.foo {
  float: left !important;
}
/* DO */

.foo.bar {
  float: left;
}

At-rules

At-rules that directly contain declarations should follow the same pattern that applies to any other rule.

/* DON'T */

@font-face {
  font-family:Foobar;
  src:local(Foobar),url(../webfonts/foobar.woff) format(woff);
  font-weight:bold;font-style:normal}
/* DO */

@font-face {
  font-family: 'Foobar';
  src: local('Foobar'),
    url('../webfonts/foobar.woff') format('woff');
  font-weight: 700;
  font-style: normal;
}

Nested rules inside at-rules should be properly indented.

  • Don’t leave a blank line before the first rule.
  • Don’t leave a blank line after the last rule.
/* DON'T */

@media(min-width:768px){

.foo {
  font-weight: 900;
  color: #222;
}

.bar {
  padding: 10px;
  margin: 0;
}

}
/* DO */

@media (min-width: 768px) {
  .foo {
    font-weight: 900;
    color: #222;
  }

  .bar {
    padding: 10px;
    margin: 0;
  }
}

Comments

Use sentence case for all kind of comments.

/* Single-line comment. */

/**
 * Multi-line comment.
 */

Use native single-line comments when working with Sass.

// Single-line comment.

////
// Multi-line comment.
//

Header comments

Use this as a header for every stylesheet.

/**
 * Component name
 * Small description of what the component does, where it’s used, etc.
 */

Use native single-line comments when working with Sass.

////
// Component name
// Small description of what the component does, where it’s used, etc.
//

Reference comments

To avoid interfering with the code reading, try to use “reference comments”.

/**
 * 1. Override inherited value.
 * 2. Fallback for browsers that don’t support `rgba()`.
 */

.foo {
  padding: 0; /* 1 */
  background: #222; /* 2 */
  background: rgba(0, 0, 0, 0.6);
}

Use native single-line comments when working with Sass.

////
// 1. Override inherited value.
// 2. Fallback for browsers that don’t support `rgba()`.
//

.foo {
padding: 0; // 1
background: #222; // 2
background: rgba(0, 0, 0, 0.6);
}

Tag comments

  • The only accepted tag is: TODO.
  • Use uppercase for the tag name.
  • Place a colon after the end of the tag name.
  • Place a space after the colon.
.foo {
  /* TODO: add fallback. */
  background: rgba(0, 0, 0, 0.6);
}

Use native single-line comments when working with Sass.

.foo {
  // TODO: add fallback.
  background: rgba(0, 0, 0, 0.6);
}

Section comments

When appropriate, break code into meaningful sections.

/* First level
   ---------------------------------------------------------------- */

/* Second level
   -------------------------------------------- */

Use native single-line comments when working with Sass.

// First level
// ---------------------------------------------------------------- //

// Second level
// -------------------------------------------- //

Appendix: Sass

Syntax

Always use the SCSS syntax. This requires the use of the .scss file extension.

Variables

  • Use variables —at least— for colors and font size.
  • Use !default only when a variable it’s likely to be modified.

At-rules

@import

  • Define one @import declaration per line.
  • Quote file names using single quotes.
  • Don’t include the leading underscore when importing a partial.
  • Don’t include the .scss file extension.
// DON'T

@import "_foo.scss", "_bar.scss";
// DO

@import 'foo';
@import 'bar';

@mixin

Use a @mixin whenever you want to generate reusable sections of code.

@extend

Avoid using @extend. Try to use a @mixin instead.

Nested rules

  • Only use nesting when absolutely necessary.
  • Never nest more than three levels deep.
  • Separate each nested rule by a blank line.
// DON'T

.foo {
  color: #000;
  .bar {
    color: #222;
    .baz {
      color: #444;
      .qux {
        color: #666;
        .quux {
          color: #999;
        }
      }
    }
  }
}
// DO

.baz {
  color: #444;

  .qux {
    color: #666;

    .quux {
      color: #999;
    }
  }
}

Never nest inside empty rules.

// DON'T

.foo {
  .bar {
    color: #222;
  }
}
// DO

.foo .bar {
  color: #222;
}

Never generate compound names using the parent selector.

// DON'T

.foo {
  color: #000;

  &__bar {
    color: #222;
  }

  &--baz {
    color: #444;
  }
}
// DO

.foo {
  color: #000;
}

.foo__bar {
  color: #222;
}

.foo--baz {
  color: #444;
}

Appendix: Vendor prefixes

Never use vendor prefixes directly in the source code.

  • Use Autoprefixer.
  • If Autoprefixer is not available, you could use a @mixin.

Exceptions

When certain property is non-standard, Autoprefixer will not perform any action.

In those situations always leave a comment explaining why you’re using that property; this will generate code easier to understand and prevent accidental removals.

// DON'T

.foo {
  color: #000;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
// DO

////
// 1. Modify default font smoothing mode. Non-standard properties;
//    explicit use of vendor prefixes is required.
//

.foo {
  color: #000;
  -webkit-font-smoothing: antialiased; // 1
  -moz-osx-font-smoothing: grayscale; // 1
}

Appendix: Linter

Remembering all this might be hard, that's why we use Sass Lint. The .sasslintrc configuration file is available in this repository. Use it!

Contributing

Contributions are welcome!

This project is possible thanks to these contributors and many other awesome people!

License

© 2013-2019 Mercado Libre. Licensed under the MIT license.