Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
SASS Modules

SASS Modules

Goals

  • modularity
  • encapsulation
  • predictability
  • extensibility
  • integrability
  • explicitness
  • readability
  • practicality
  • maintainability
  • semantic

Paradigms

SMACSS - Modules

  • SMACSS introduces modularity
  • modules encapsulates semantic elements
  • modules are extendable
  • modularity and encapsulation enables clean integration with other elements
  • modules have predictable specificity. Important for modifying styles.

BEM (Block Element Modifier)

  • BEM introduces class naming structure
  • class naming structure makes element relationships explicit
  • class naming structure promotes coding standards

Modules

Encapsulation achieved through module namespacing instead of SASS nesting

.module
.module--modifier
.module__component

Module Base

Base module element; defines base styles

// scss
.status
.ad-banner

// html
<div class="status"></div>
<div class="ad-banner"></div>

Module Modifier

Modification to module/component styles

// scss
.status--alert
.status--code-red
.status__label--huge

// html
<div class="status status--alert">
	<div class="status__label status__label--huge"></div>
</div>

variant with modifiers

avoid using more than 2 modifiers on an element:

  • it avoids being too presentational in the markup

      <div class="status status--alert status--huge status--code-red status--rounded status--some-modifier"><div/>
    
  • if an element needs more than 2 modifiers, @extend the module to create a variant module to apply extra modifiers and custom styles to make a more semantic module

caveat

CSS cascade may be important for modifiers, as it might override module base styles. Place Module Modifier declarations below Module Base declaration.

case study: module state

prefix state modifiers with is-. usually toggled by javascript.

2+ module modifier caveat does not apply to module states as it gets applied dynamically

// scss
.status--is-hidden
.status--is-selected

// html
<div class="status status--code-red status--is-hidden"></div>

Module Component

children elements of a module

// scss
// module
.status

// component
.status__label
.status__start-date
.status--alert__icon

// html
<div class="status">
	<div class="status__label"></div>
</div>	

avoid more than 2 levels of component:

  • long class selectors can occur

      .some-module__some-component__subcomponent-name__subsubcomp
    
  • it creates a restriction on module complexity; maintaining modularity

  • if a module requires more than 2 levels of components, create different modules for those components

When I first started writing modules like this I’d often end up with huge modules with complex class names… most child components can be extracted out into their own standalone modules. So if you leave the positioning up to the parent, we end up with smaller, standalone modules. - source

case study: collections module

module structure on collections may look this way, but .words__word styles could get more complicated

.words
.words__word
.words__word--modifier
.words__word__component

instead:

.words
.word
.word--modifier
.word__component

instead of using -list, pluralize collection container: end with an s


Nested Module

a module inside another module

	<div class="content">
		<h1 class="headline"></h1>
	</div>

Here, there are two circumstances for .headline

  • it is styled that way because it’s in .content, or
  • whether it just happens to live in .content.

If it is the latter then it's a simple nesting. If it's the former then it's a complex nesting. .content serves as the base module, while .headline serves as the nested module

simple nesting

nested module that can stand on its own without any modification inside a base module

simply drop the module into the markup

	// scss
	.post 
	.advertisement
	
	// html
	<div class="post">
		<div class="advertisement"></div>
	</div>

complex nesting

nested module that needs modification in order to be styled properly inside a base module (module context styling)

@extend nested module as a component for the base module. Use the nested module namespace for the base module component.

// scss
.sidebar__advertisement {
	@extend .advertisement;
	box-shadow: none;
}

// html
<div class="sidebar">
	<h1 class="sidebar__advertisement"></h1>
</div>

@extending the nested module will make the relationship explicit with the original module. Any modifications to the nested module are completely encapsulated in the base module.

A module should only manage its contents, and nothing outside of it: siblings and parent elements. This will ensure encapsulation completely within the module. Thus, nested module should not style when it's in a base module. Instead, the base module should style nested modules, if needed.

// BAD
.advertisement {			// advertisement module
	background-color: blue;
	color: white;
}		
.post .advertisement {		// advertisement module in post module context 
	color: grey;
}


// GOOD
.advertisement {			// advertisement module
	background-color: blue;
	color: white;
}

.post {						// post module
	padding: 10px;
}
.post__advertisement {		// post component: advertisement
	@extend .advertisement;
	color: grey;		
}

Variant Module

a separate module for extending or modifying base module styles or a reoccurring combination of the base module. Primarily applies to module element with more than two modifiers applied to it.

.status-modal {
	@extend .status;
	@extend .status--alert;
	@extend .status--rounded;
	@extend .status--huge;
	
	// dead centre layout w/ flex
	@include flexbox;
	@include flex-direction(column);
	@include justify-content(center);
	@include align-items(center);
}

if a variant overrides many styles of the base module, it is essentially a completely different module. Refrain from extending the base module. Create a new module.

Scaffold Module

an extend-only module used as a scaffold for other modules and can't be used by itself e.g. grid-systems & layouts

It helps avoid presentational markup and promote sematic modules

%media-object // Nicole Sullivan's Facebook layout object

.news-feed-post {
	@extend %media-object;
}

Caveats

  • Extending modules (variant/nested-complex modules) might make it hard to debug/read on the browser dev toolkit when many other modules/elements extended the same modules

Resources

This is an excellent guide, thanks for sharing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment