Our Approach to Writing CSS

We use SCSS to write our CSS. All components should keep their CSS local to their own component (e.g. use Button/styles.scss next to Button/index.js). Here are a few guidelines for writing scalable CSS:

  • Use component names for class names: if your component is SearchResult, its class name should be .SearchResult. Any children component should start with the component name, e.g. .SearchResult-listItem, etc. Any utility classes like enabled or disabled should be written with two dashes, e.g.: .SearchResult-textInput--enabled.
  • Always use variables for colors, margins, and sizes: these should be app-wide variables whenever possible to keep them shared between components; when we change the link color it should change everywhere.
  • Do not import directly from ~core/: each app has its own mixins.scss, vars.scss, etc. Use ~amo/css/mixins.scss instead of ~core/css/mixins.scss. Each app extends core but be careful of changing things in core; it's best to put overrides in an app's mixin.
  • Use px (pixels) for size instead of em, rem, etc.: pixel sizes work fine and keeps things consistent. If you want to scale something with screen size % (percent) values are okay.
  • Keep CSS local to the component: don't use App.scss or SearchPage/styles.scss to style a button component on a SearchPage component. Instead create options that can be passed to differently style the button from the SearchPage component.
  • Don't nest selectors; use more specific class names instead: prefer <ul className="List"><li className="List-item"></li></ul> and the selector .List-item over .List li. This seems verbose but it prevents nesting bugs and confusion as the codebase grows. It also makes it easier to scan CSS rules at a glance.
  • Don't use the parent selector, except for pseudo-classes: prefer full class names, it is easier to find. Using & for pseudo-class such as :hover, :active, etc. is allowed though.
  • When overrides make sense, keep them in the parent component and use CSS nesting: this is the only time we use nesting instead of specifically-named class selectors. There are a few cases where tiny adjustments may be made to margin, etc. for a child component in only one context. If modifying the margin of Result inside SearchResultList, it is appropriate to declare .SearchResultList .Result in SearchResultList/styles.scss.