HTML & CSS
Article

Introducing CCSS (Component CSS)

By Satheesh Kumar

CCSS, or Component CSS, is an architecture that simplifies the CSS authoring experience for large web applications.

Large web applications generally have a lot of CSS files and often have many developers working on those files simultaneously. With the advent of so many frameworks, guidelines, tools, and methodologies (OOCSS, SMACSS, BEM, etc.), developers need a CSS architecture that is maintainable, manageable, and scalable.

As a frontend engineer, I believe that component-based web development is the way forward. Web components are a collection of standards that are working their way through the W3C. They allow us to bundle up markup and styles into reusable HTML elements that are truly encapsulated. What this means is we need to start thinking about component-based CSS development. While the browser makers are implementing these standards, we can use soft-encapsulation in the meantime.

Let’s take a look at exactly what CCSS is and how you can use it in you are setting up the CSS architecture for a complex web application.

Elements of CCSS

Below are the major elements used either fully or in a modified way to achieve the best configuration for the CCSS architecture.

SMACSS

SMACSS, created by Jonathan Snook, stands for Scalable and Modular Architecture for CSS. It is more of a style guide than a rigid framework. Read about SMACSS for background on the structure as CCSS uses it.

BEM

BEM, created by developers at Yandex, stands for “Block”, “Element”, “Modifier”. It is a front-end methodology that is a new way of thinking when developing web interfaces. The guys at Yandex came up with BEM and more information can be found in Harry Roberts’ excellent article.

Sass

Sass is CSS with superpowers. I highly recommend it but you can also use Less if you prefer. Please refer to the Sass documentation for more information.

Compass

Compass has no class definitions; it is an extension for Sass that provides a lot of utilities. It is used for general useful mixins, and sass compilation. Compass mixins should nearly always be used in cases where vendor prefixes are required. This again is a nice-to-have and Bourbon, on the first look is a great alternative.

Principles of CCSS

Let’s now look at the main principles of CCSS.

Component-based

Write small and independent components that are reusable. A reusable CSS component is one that does not exist only on a specific part of the DOM tree or require the use of certain element types. If necessary, extra HTML elements should be used to make a component reusable.

Modular and Isolated

Components should have everything necessary for a certain part of the UI and have a single focus. Each component should be isolated, meaning it does not directly modify or depend on another component.

Isolation is more important than code reuse across components as reuse can increase dependencies and tight coupling, eventually making the CSS less manageable.

Composable

When authoring CSS in a way that aims to reduce the amount of time spent writing it, one should think of it in a way to spend more time changing HTML classes on elements for modifying or adding styles. It is much easier for all developers to author CSS when it is like assembling lego blocks than to fight the CSS war. CSS classes are the building blocks that should be used to compose styles.

Predictable

Predictability means when you author CSS, your rules behave as you expect. This is important for large applications that have many pages. Avoid using overly complicated selectors and generic class names, as these can lead to unpredictable CSS.

Documentation

Most people assume CSS is self-explanatory. In fact, this is usually not the case! CSS components must have clear documentation that describe what they do and how they should be used.

Directory Structure

Below is an example directory structure for easier visualization. I have also included an example setup in the CCSS GitHub repo.

styles
    ├── bootstrap.css
    ├── ext
    │   ├── bootstrap
    │   │   ├── _settings.scss
    │   │   └── bootstrap.scss
    │   └── font-awesome
    │       └── font-awesome.scss
    ├── font-awesome.css
    ├── images.css
    ├── main.css
    └── scss
        ├── _config.scss
        ├── base
        │   ├── _animation-classes.scss
        │   ├── _base-classes.scss
        │   ├── _base.scss
        │   └── images.scss
        ├── components
        │   ├── directives
        │   │   ├── _empty-state.scss
        │   │   ├── _legend.scss
        │   │   └── _status-message.scss
        │   ├── pages
        │   │   ├── _404.scss
        │   │   └── _redirect.scss
        │   └── standard
        │       ├── _alarm-state.scss
        │       ├── _graph-message.scss
        │       └── _panel.scss
        ├── main.scss
        ├── mixins
        │   ├── _animation.scss
        │   ├── _bem.scss
        │   └── _icon.scss
        └── themes
            └── _light.scss

Only edit/author the files in the scss/ folder in the folder tree shown above. This allows for updating external libraries easily, which are in the ext/ folder. Many applications start out with an external CSS framework like Bootstrap or Foundation, so I added them in the example setup inside ext/. But it’s absolutely fine to have all the CSS written from scratch; everything else mentioned above still applies.

The example components/ directory is well-suited for an AngularJS application, but can be customized for other frameworks or applications. More information is in the “Architecture” section below.

In the HTML page, include all the .css files from the style/ folder, which contains all the compiled CSS (from Grunt, Compass, etc.). Never alter them.

Naming Conventions – Simplified BEM

  • u-className – Global base/utility classes
  • img-className – Global image classes
  • animate-className – Global animation classes
  • ComponentName – Standard Components (B)
  • ComponentName-elementName – Component’s Element (E)
  • ComponentName--modifierName – Component’s Modifier (M)

Note the UpperCamelCase Component name style to indicate that it is the master element; this denotes that it is the boundary of the component. Element and modifier names are elementName and modifierName, respectively. Do not use a hyphen (-) to separate out component names, as these signify the start of an element/element name.

Architecture and Design

Let’s consider the architecture encouraged by CCSS.

Grunt

Grunt is a great task runner that can automate many common chores (such as compiling CSS or validating HTML). There are also other task runners; an ideal workflow involves using one to watch files under development and recompile the CSS when changes are made.

File Organization

Look again at the directory structure, which is derived from SMACSS. Notice the ext/ directory, which contains all external frameworks (like Bootstrap). To keep upgrading easy, these should not be modified; instead, overrides and extensions should be placed in the base/ directory.

base/ is where you keep global base styles that are used application-wide.

_base.scss are base styles for element selectors only. These are sort of “CSS resets”.

_base-classes.scss are all utility classes used application-wide across many pages, views, and components. Prefix class names with u-

images.scss is used as an SCSS compilation source. It should define and inline all site images as Data URIs. /app/styles/images.css is generated from this file.

_animate.scss holds all application-wide animation classes.

_bootstrap-overrides.scss holds the framework overrides only. Sometimes the level of specificity of framework selectors is so high that overriding them requires long specific selectors. Overriding at a global level should not be done in the context of an SCSS component. Instead, all global overrides go here.

Components

Any unit of reusable CSS not mentioned above is considered a “component”. We use AngularJS so I categorized them to 3 types of CSS components: view/page, directive, and standard; hence the directory structure derived from SMACSS.

In the example setup in the GitHub repository, I created explicit folders to be clear. If your application is small, you may put them in one folder. All components follow the modified BEM naming convention in combination with the CamelCase. This got me great wins in encouraging other team members to follow BEM-style syntax. It also avoided a lot of confusion when moving away from using the typical BEM style with the -, --, and __ characters, which generate class names like module-name__child-name--modifier-name!

It is also important that the CSS class definition order in a component reflects the HTML view. This makes it easier to scan, style, edit, and apply classes. Finally, it’s a good idea to have an extensive style-guide for the web application and follow guidelines for CSS and Sass (e.g. avoid @extend).

CCSS Example

Refer to the code for an example setup of the CSS.

Here is an example component in Sass:

.ProductRating {
  // nested element
  @include e(title) {
    ...
  }
  // nested element
  @include e(star) {
    ...
    // nested element's modifier
    @include m(active) {
      ...
    }
  }
}

This compiles to the following CSS:

.ProductRating {
  ...
}
// nested element
.ProductRating-title {
  ...
}
// nested element
.ProductRating-star {
  ...
}
// nested element's modifier
.ProductRating-star--active {
  ...
}

And your HTML might look something like this:

<div class="ProductRating">
  <img alt="Company logo" class="img-logo">
  <h3 class="ProductRating-title">Title</h3>
  <div class="u-starHolder">
    <span class="ProductRating-star ProductRating-star--active"></span>
    <span class="ProductRating-star ProductRating-star--active"></span>
    <span class="ProductRating-star ProductRating-star--active"></span>
    <span class="ProductRating-star"></span>
  </div>
</div>

You can refer to the simplified BEM mixin, which uses reference selector to achieve this and is simpler than @at-root. Working with BEM became much easier in Sass 3.3+, which gives us the ability to write maintainable code that is easy to understand.

Contributing

Contributions in the GitHub repo in the form of issues/PRs for adding more examples, improvements with post processing, clarifications, etc. are most helpful.

And be sure to check out the repo for credits and useful resources related to CCSS. If you have any questions or comments, post them in the comments below or on the GitHub repo.

Free Guide:

7 Habits of Successful CTOs

"What makes a great CTO?" Engineering skills? Business savvy? An innate tendency to channel a mythical creature (ahem, unicorn)? All of the above? Discover the top traits of the most successful CTOs in this free guide.

  • Josh Bambrick

    Surely it is a better approach to stop worrying about vendor prefixes – write normal css and use grunt to add prefixes. I don’t see any good reason why compass is necessary.

    • Thomas Semmler

      Maybe you have your scss in your git repo, but not your compiled css, because you want to compile your css directly on the remote server. Not everybody runs node for a page that is mainly built to serve content.

      Besides, not everybody uses grunt or the command line at all. I use codekit for all my projects and besides just vendor-prefixing, I also use compass for slicing and use a few of their blueprint mixins. And a lot of people got into compass just because of the option to easily manage vertical rhythm. In order to use older versions of susy, you also need compass.

      It just purely depends on your personal workflow. Either way is fine imho.

      • Josh Bambrick

        Whatever works – of course not everybody uses grunt, although there are gui tools available for auto prefixing. I was more mentioning because the article only suggested using compass for vendor prefixes and also mentioned using grunt. I would say that it is probably a bit more future proof to add prefixes in your compilation step as it allows you to move away from compass more easily and means that you don’t need to worry about prefixes at all when you are writing code – but the difference is probably minimal.

    • Satheesh Kumar

      Compass like @Thomas Semmier mentioned has other useful mixins. Auto prefixing is one of the things it does and it’s not a necessity but a nice to have as mentioned in the article.

      • Josh Bambrick

        That’s fine, I just wouldn’t agree at all that “Compass mixins should nearly always be used in cases where vendor prefixes are required”

    • MattDiMu

      I’m also currently thinking about replacing vendor-prefix-mixins with autoprefixr. Still I would never remove SASS/Bourbon at all, as can do so much more and they make the CSS-Projects so much more maintainable :)
      By the way – how do you do spriting or handling svg with png-fallback? That’s probably the main reason why i keep Compass.

  • Kelderic

    My problem with this is near your first paragraph, where you mention that a guiding principle is that duplication is preferable if is supports the isolation of styles. My problem with this is that while it may make things easier from a development perspective, it makes things worse from a user perspective because it’s going to lead to code bloat as things that could be combined become duplicated.

    • http://www.sathify.com/ Satheesh Kumar

      Nicole’s talk http://www.slideshare.net/stubbornella/our-best-practices-are-killing-us will clear up any concerns you might have about file size and bloat from users perspective.

      Further you are minifying and gziping the file. Any comparisons should be made after the HTTP compression and you will discover the advantages of isolating styles.

      This doesn’t mean I’m asking you to duplicate all styles, if any style is re-used application wide it should be in `/base’ folder.

      • Johan Van den Rym

        Like uncss can remove unused styles, you could use http://zmoazeni.github.io/csscss/ to scan your CSS for duplicate styles. That way you do not have to worry about it.

  • MattDiMu

    I don’t see the advantage of combining BEM and a Preprocessor like SASS. BEM was/still is a great guide for pure CSS-Projects. Preprocessors with their nested rules, however, make this guide superfluous. Just compare:

    .component {
    .modifier {

    }
    }

    with your proposed

    .component {
    @include e(class) {

    }
    }

    If i use the nested rules, I’ve got as well the advantage of “scoped” components, but
    – it’s less css to write
    – it’s less html to write
    – it’s much more intuitive (just use the css selectors the way you know them)
    – what if i wanna use some “special” selectors like a[href$=”.jpg”] {…} ?

    • http://www.sathify.com/ Satheesh Kumar

      I agree it’s more cleaner but when the nesting becomes complicated the css becomes a mess with lot of selectors. SASS mixin compiles these nested styles and puts them at the root level

      BEM with SASS allows you to write “nested” selectors which would ultimately be compiled at the root. Please also take a look at the mixin to simplify the BEM syntax.

      SASS also gives you so much more than this lie source maps, variables, etc.

      • MattDiMu

        tbh i don’t get your point. Why would SASS-nesting become a mess while the CCSS would not? Could you give me a concrete example?

        • http://www.sathify.com/ Satheesh Kumar

          CCSS is an architecture which uses SASS, BEM, etc. Please read the above answer for your question of why use SASS with BEM, I’m all for SASS because it allows you to write “nested” selectors which would ultimately be compiled at the root.

          Please look at the output css in the example https://github.com/sathify/CCSS#example and the SASS mixins which allow you to do that https://github.com/sathify/ccss/blob/master/styles/scss/mixins/_bem.scss

          Just simply nesting will give you .ProductRating.ProductRating-star.ProductRating-star–active etc. and that complicated css is avoided when its compiled at the root.

  • https://twitter.com/dmathisen36 dmathisen

    Edit to my last comment (I can’t find it)… I just realized that this article’s author is the creator of CCSS. That changes everything, so I take back my last comment. Sorry.

    • OphelieLechat

      All good, @dmathisen:disqus — your comment was held up in moderation because of the link. As you noticed, the author also posted this on GitHub, this is all posted with permission and billed accordingly. If we’d just ripped off someone’s GitHub repo, that would be 100% worth calling out!

  • http://meiert.com/en/ Jens O. Meiert

    We do face a good number of challenges with complex sites and apps. It’s an important topic well worth more research and debate.

    Especially on a larger scale, however, it matters to follow principles of professional web development. Two major ones are to tailor code to project needs, and to keep code as minimal as possible. I don’t see how “CCSS” addresses tailoring and minimalism—could you add to these points?

    Furthermore, can you share more about CCSS in position to OOCSS, and how it does avoid running into what effectively still stalls OOCSS [1]? I think this can help for general orientation in this space.

    [1] http://meiert.com/en/blog/20130806/object-oriented-html-and-oocss/

    • http://www.sathify.com/ Satheesh Kumar

      RE minimalism: Nicole’s talk http://www.slideshare.net/stub… will clear up any concerns you might have about file size and bloat from users perspective. Further you are minifying and gziping the file. Any comparisons should be made after the HTTP compression and you will discover the advantages of isolating styles. This doesn’t mean I’m asking you to duplicate all styles, if any style is re-used application wide it should be in `/base’ folder.

      Re I have always used SMACSS and now with combination of BEM. Never OOCSS. That said CSSS is a component based CSS architecture (not a framework) which greatly improves CSS authoring experience.

  • MattDiMu

    Yeah, i’ve read the examples and still don’t get the advantage of it. Why would i get “.ProductRating .ProductRating-star .ProductRating-star–active”? I think, that it would more likely be something like “.ProductRating .star.active” if i use “normal” SASS nesting. True, i lose the information whether a class is an element or just a modifier, but that should be manageable by using appropriate naming like “.active” or “.button.blue”.

    What I’m trying to say (like in my first post) – i cherish BEM in pure CSS Projects as it keeps the code better readable/maintainable, but I don’t think, that it’s necessary in SASS-Projects, where the “normal” nesting provides even easier code.

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in Front-end, once a week, for free.