Toggle

Features

Features are a project’s modules and user interface elements that are too specialized for use across multiple sites. They might assume a certain context or content type, and in other cases, they might include thematic styles or responsive layout.

In an AngularJS application they come with their specific templates and controllers and contain only the styles used for this specific unit.

app.js
dashboard/
  dashboard-controller.js
  dashboard.html
  dashboard.scss
auth/
  auth-controller.js
  auth.html
  auth.scss
  login/
    auth-login-directive.js
    auth-login-directive.scss
layout/
  layout.scss
  header/
    header.html
    header.scss

Special importance is given to the layout folder. It contains the layout.scss which describes the basic layout of the application. Furthermore, the folder contains styles and templates for header, footer and other globally used elements in the application.

When should I add Features?

When explaining what characterizes a Component versus a Structure, we outlined a few considerations that help us determine between the two:

  • Size of scope
  • Dependencies on other modules
  • Portability between projects, or lack thereof

Size of Scope

When a module affects different aspects of an element or arrangement of elements simultaneously (i.e., it has a wide scope), that’s a very strong indicator that you’re dealing with a Structure.

Let’s say, for example, you’re designing a fairly common site header: logo on the left, plus some horizontal navigation on the right. You could realistically build this pattern using a combination of Helpers, Components, and Tools.

<header class="group">
    <img class="fl" src="logo.svg" alt="Website">
    <nav class="fr">
        <ul class="list list--inline">
            <li class="list-item"><a href="/">Home</a></li>
            <li class="list-item"><a href="/blog">Blog</a></li>
            <li class="list-item"><a href="/contact">Contact</a></li>
        </ul>
    </nav>
</header>

But what happens when we try to make our site responsive? On small-screen devices, we want our navigation to also:

  • Fill the viewport width
  • Stack links atop one another
  • Apply an alternating background color to each list item

See the problem? Our module definitely isn’t list--inline anymore. It now needs its own aesthetics and responsive behavior—both of which are tailored to their surrounding design. Although we might use this pattern in multiple places on the site, its broad scope makes copying it across different designs unlikely. In this case, our best bet is to create a new Structure, and define our new themed, responsive list module inside.

Dependencies

Unlike Components, Structures can depend on, or even extend, pre-existing Components. This is useful when you want to add theme or behavior to a Component, but keep any unique changes contained within their own module.

In NGSCSS, we use our g (grid) Component primarily for page layout. We try to keep it simple and assume as little as possible, but there are cases where we want to include similar functionality inside of a more specific module. Float-based grids don’t always behave predictably when their items have variable a height, so we’ve defined a collection Structure to add contextual clearfixing.

.collection {}

// -------------------------------------
//   Modifiers
// -------------------------------------

.collection--1of3 {

  .collection-item:nth-child(3n + 1) {
    clear: left;
  }
}

// -------------------------------------
//   Scaffolding
// -------------------------------------

// ----- Item ----- //

.collection-item {
  margin-bottom: $b-space-l;
}

Using both the g (grid) Component and the collection Structure, we can apply both modules' classes directly in the markup.

Note: applying multiple modifiers to grid and grid-box can make markup difficult to read quickly, so we’ve shortened the classes to g and g-b.

<div class="g collection collection--1of3">
  <div class="g-b g-b--1of3 collection-item">
    <!-- Content -->
  </div>
  <div class="g-b g-b--1of3 collection-item">
    <!-- Content -->
  </div>
  <div class="g-b g-b--1of3 collection-item">
    <!-- Content -->
  </div>
  <div class="g-b g-b--1of3 collection-item">
    <!-- Content -->
  </div>
</div>

But that’s a lot of classes to keep track of! Luckily, Sass can help us simplify our markup thanks to its @extend directive.

.collection {
  @extend .g
}

// -------------------------------------
//   Modifiers
// -------------------------------------

.collection--1of3 {
  @extend .g-b--1of3;

  .collection-item:nth-child(3n + 1) {
    clear: left;
  }
}

// -------------------------------------
//   Scaffolding
// -------------------------------------

// ----- Item ----- //

.collection-item {
  @extend .g-b;
  margin-bottom: $b-space-l;
}

And now we apply only a single set of classes in the markup.

<div class="collection collection--1of3">
  <div class="collection-item">
    <!-- Content -->
  </div>
  <div class="collection-item">
    <!-- Content -->
  </div>
  <div class="collection-item">
    <!-- Content -->
  </div>
  <div class="collection-item">
    <!-- Content -->
  </div>
</div>

Portability

In the end, limiting scope and minimizing dependencies both affect portability, which is usually our biggest concern when classifying modules. If you can easily tweak a few lines of CSS inside a module and use it between projects, that means it’s reasonably portable, and you have solid grounds for classifying it as a Component. On the other hand, if try to port a module and find yourself rewriting a significant amount of code, then the module is likely better classified as a Structure.