Key Takeaways
- CCSS (Component CSS) is a CSS architecture designed to simplify the authoring experience for large web applications, making it maintainable, manageable, and scalable. It encourages component-based web development, where markup and styles are bundled into reusable HTML elements.
- The main principles of CCSS include creating small, independent, reusable components; ensuring components are modular and isolated; writing CSS that is composable and predictable; and documenting all CSS components clearly.
- CCSS utilizes a specific directory structure and naming conventions, largely based on the SMACSS and BEM methodologies. It also promotes the use of task runners like Grunt for automating common tasks, such as CSS compilation or HTML validation.
- CCSS improves the scalability, maintainability, and performance of web applications by making styles modular, reducing the risk of styles clashing across the application, and allowing the browser to parse only the styles for the components being rendered. It’s compatible with any JavaScript framework and can be used with CSS pre-processors like Sass, Less, or Stylus.
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 classesimg-className
– Global image classesanimate-className
– Global animation classesComponentName
– 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.
Frequently Asked Questions about Component CSS (CCSS)
What is the main difference between CCSS and traditional CSS?
Traditional CSS is a style sheet language used for describing the look and formatting of a document written in HTML. It is designed to enable the separation of content from presentation, including layout, colors, and fonts. On the other hand, CCSS (Component CSS) is a modern approach to styling where styles are directly linked to their specific components. This means that the styles are scoped locally to the component, reducing the risk of styles clashing across your application. This approach makes your styles more maintainable, modular, and easier to scale.
How does CCSS improve the scalability of a project?
CCSS improves the scalability of a project by making the styles modular. In traditional CSS, as the project grows, the CSS file also grows, making it difficult to manage. However, in CCSS, each component has its own style, making it easier to manage and scale. You can easily update or modify a component without affecting the rest of the application.
Can I use CCSS with any JavaScript framework?
Yes, CCSS is compatible with any JavaScript framework. Whether you’re using React, Angular, Vue, or any other framework, you can use CCSS to style your components. This makes CCSS a versatile tool for any front-end developer.
How does CCSS handle global styles?
While CCSS is primarily used for styling individual components, it can also handle global styles. You can define global styles in a separate file and import them into your components as needed. This allows you to maintain a consistent look and feel across your application while still benefiting from the modularity of CCSS.
What are the benefits of using CCSS over inline styles?
Inline styles, while easy to use, have several limitations. They can’t use media queries, pseudo-classes, or pseudo-elements. They also have the highest specificity, which can lead to difficulties in overriding styles. CCSS, on the other hand, offers the full power of CSS, including the ability to use media queries, pseudo-classes, and pseudo-elements. It also has a lower specificity than inline styles, making it easier to override styles when necessary.
How does CCSS improve the performance of a web application?
By scoping styles to individual components, CCSS can significantly improve the performance of a web application. In traditional CSS, the browser has to parse the entire CSS file to render a page, which can slow down the rendering process. However, with CCSS, the browser only needs to parse the styles for the components that are currently being rendered, resulting in faster page load times.
Can I use CSS pre-processors with CCSS?
Yes, you can use CSS pre-processors like Sass, Less, or Stylus with CCSS. This allows you to leverage the power of these pre-processors, such as variables, mixins, and nested rules, while still benefiting from the modularity and scalability of CCSS.
How does CCSS handle CSS specificity?
One of the main advantages of CCSS is that it eliminates the problems associated with CSS specificity. Since each component has its own styles, there’s no need to worry about styles clashing or overriding each other. This makes it easier to manage your styles and reduces the risk of bugs related to CSS specificity.
Can I use CCSS for responsive design?
Yes, you can use CCSS for responsive design. Just like traditional CSS, CCSS supports media queries, which allow you to apply different styles depending on the device’s screen size. This makes it easy to create a responsive design that looks great on all devices.
How does CCSS improve the maintainability of a project?
CCSS improves the maintainability of a project by making the styles modular and easier to manage. Each component has its own styles, so if you need to update or modify a component, you only need to change the styles for that specific component. This reduces the risk of introducing bugs and makes it easier to update or refactor your code.
Satheesh is a Front-end Engineer from San Francisco with a passion for building products with exceptional user experience.