Choosing how to structure our CSS components

Do you remember when working with CSS was like add <style>/* */ </style> to your index.html just before the <script>/* */ </script> 🙄 ?

Fortunately those days are far behind right? everything related to style sheets has evolved a lot, is something that always happens with things of Frontend, we love to change them, update them or complicate them. Sometimes we keep imagine and people decide to create functional CSS.

Then came a customer and ask about to create a new project… Now what? Plan for a minimum structure and some basic agreements, in the following lines I will try to show a little how I like to do it and how I think it should be.

Something that logically has not come out only from me, is thanks to hours of discussion and beer (or tea) with Borja, Edu, Carlos, Carrillo or Alex among others.

Of course, we are not trying to reinvent the things, we are based in existing agreements, in this case BEM and BEMIT agreement, other agreements and logically in our small contributions.

BEM — Block Element Modifier

It is one of the agreements that I most like, we have been able to put it into practice in many real projects (with some modifications) and the results are excellent, but, as always, meanwhile you are working you start to see problems or things that you need to change to suit your needs, but it’s great.

It is based on a very simple structure, we have blocks that are inside elements and these elements can have modifiers.

/* Author block */
.author { ... }
/* Image element */
.author__image { ... }
/* Rounded image */
.author__image--rounded { ... }

And the HTML

<div class="author">
<img class="author__image author__image--rounded" alt="" />
</div>

The interesting thing about this is that .author has become a ‘component’ pretty reusable and easy to change.

When you start to work with different libraries that use this agreement could be that there are some repetitions, to avoid that we use modules, with a prefix.

/* Author block */
.ck-author { … }
/* Image element */
.ck-author__image { … }
/* Rounded image */
.ck-author__image--rounded { … }

And working with SASS is better 😁

.ck {

/* Author block */
&-author {


/* Image element */
&__image {


/* Rounded image */
&--rounded {


}
}
}
}

Some things about BEM

To work with BEM you can choose two paths, follow the agreement in a way completely strict or based it to adapt it to your needs and ideas for the project or team (BEMIT and other ideas)

I think better the second. If you work in a product, probably you will search for a method that will be nice for your team and you will be adapting it all the time. I think (working in consulting company) that the best is to adapt each methodology to the project, the client and the respective team.

There are some methodologies and tips that I like:

  • Change ‘__’ with ‘-’ in block-element: It feels more useful and confortable to use in my day to day.
/* Author block */
.ck-author { … }
/* Image element */
.ck-author-image { … }
/* Rounded image */
.ck-author-image--rounded { … }
  • Use ‘_’ for whitespaces: Instead of be like 15 minutes trying to write something with only one word (do it always if is posible!) you can use ‘_’ to the whitespaces ‘my_page’.
/* No */
.ck-authorBox { … }
/* Yes */
.ck-author_box { … }
  • Don’t use more than 1 level of deep: All the elements inside of a block have to ve children from the father.
<!– No –>
<div class="ck-author">
<div class="ck-author-info">
<span class="ck-author-info-email"></span>
</div>
</div>
<!– Yes –>
<div class="ck-author">
<div class="ck-author-info">
<span class="ck-author-email"></span>
</div>
</div>
  • Use utilities, responsive suffixes and states: Not all the things are block and elements, there are more tools that can help us.

Utilities

As you’re working with BEM, you start to see that there are certain things that make more dependent and less reusable component. That’s where come the utilities.

Continuing with the example of the ‘author’ component, to create it are going to define a set of styles that you will be applied.

.ck-author {
background-color: white;
box-shadow: 0px 0px 50px -10px rgba(0, 0, 0, .4);
display: table;
width: 400px;
}
.ck-author-image {
display: table-cell;
max-width: 100px;
}
.ck-author-info {
color: #333333;
display: table-cell;
padding: 2%;
vertical-align: top;
}
.ck-author-name {
color: #0EAD87;
font-size: 1.2em;
font-weight: 300;
}
.ck-author-email {
text-decoration: underline;
}
<div class="ck-author">
<img class="ck-author-image" src="http://i.imgur.com/V2Pb5B1.png">
<div class="ck-author-info">
<span class="ck-author-name">Quique Fdez. Guerra</span>
<span class="ck-author-email">quique@mycompany.com</span>
</div>
</div>

In an ideal world it would be enough, but when we put this element in a real context always end up missing some details. For example you place this component in a column that has no interior padding and all your text is aligned to the right.

.ck-author {

float: left;
padding: 5px;
text-align: right;
}

But these details are not necessary for the component itself, I need them by the place where is placed, if you move it to another place surely would not need it. In addition this won’t happen only in this component, it is likely to happen with several of the components we create. So it is easier to have a module with utilities, so that if in this case we create these classes.

.u-float-left {
float: left;
}
.u-p-5 {
padding: 5px;
}
.u-text-right {
text-align: right;
}

Using them like:

<div class="ck-author u-float-left u-text-right u-p-5″>

</div>

Using SASS:

.ck {
&-author {
background-color: $color-background-light;
box-shadow: 0px 0px 50px -10px rgba($color-background-dark, .4);
display: table;
width: 400px;

&-image {
display: table-cell;
max-width: 100px;
}
        &-info {
color: $color-foreground-semidark;
display: table-cell;
padding: 2%;
vertical-align: top;
}
        &-name {
color: $color-primary;
font-size: 1.2em;
font-weight: 300;
}

&-email {
text-decoration: underline;
}

}

}
// utilities.scss

.u {
&-float {

&-left {
float: left;
}
}
// Padding with generator like https://gist.github.com/CKGrafico/0864109a512c1cc44110
&-text {

&-right {
text-align: right;
}
}
}

Responsive suffixes

Something very interesting that we saw in the article about BEMIT are the responsive suffixes, that can help us to structure our css, for this case examples are directly in SASS.

We define a few sizes that we are going to use, I quite like the way in which Bootstrap makes it.

$screen-xs: 480px;

$screen-sm: 768px;

$screen-md: 992px;

$screen-lg: 1200px;

Or t-shirts way:

$screen-xs: 480px;

$screen-s: 768px;

$screen-m: 992px;

$screen-l: 1200px;

Now we can use them in two different ways, for components or utilities.

  • For components, I recommend this way:
.ck {
/* Author block */
&-author {
@media screen and (min-width: $screen-lg) {
width: 700px;
}
}
}

Are things that are directly depending of this element, not about the context.

  • But if I want things depending of the context:
// utilities.scss
.u {
&-hidden{
display: none;
        &\@sm {
@media screen and (min-width: $screen-xs) and (max-width: $screen-sm) {
display: none;
}
}
}
}

HTML:

<div class="ck-author">
<img class="ck-author-image u-hidden@sm" src="http://i.imgur.com/V2Pb5B1.png">

</div>

States

You can start to notice that the utilities are not enough and that there are certain things that can separate and enter into a new agreement, it can happen with the states.

Some examples of states could be:

  • A component is disabled .is-disabled
  • A component is hidden .is-hidden
  • A component is active .is-active

You can see on these previous cases that in the end this is another module that instead of calling it ‘utilities’ we change to ‘states’.

Let’s se some examples:

// states.scss
.is {
&-disabled {
opacity: .5;
}
}
// author.scss
.ck {
&-author {

&.is-disabled{
font-size: .7em;
}
}
}

js-* classes

These classes are useful when we want to access an element of the DOM using JavaScript and we don’t want to affect the structure of components that we have created.

Thanks to this kind of classes if we work on projects in which more than one person is going to play those same components and logic that associates them we will have less change of have conflicts between us.

On the other hand, with the arrival of components, I have tried to reduce the use of these classes and put them only when is a third party who needs to use the selector, i.e. If the JavaScript code needed by this selector is logic of the component itself prefer to use classes as selector and not to put these special classes, since this logic is completely attached to the component and is not independent of it.

<div class="ck-author">
<img class="ck-author-image" src="http://i.imgur.com/V2Pb5B1.png">
<div class="ck-author-info">
<span class="ck-author-name js-name">Quique Fdez. Guerra</span>
<span class="ck-author-email js-email">quique@mycompany.com</span>
</div>
</div>

Don’t forget

All are recommendations, agreements and ideas from some people, the most important thing is always to do the best for the project and the team. If they liked you take some ideas and think your own methods to continue improving and trying to improve the project.

Note: If you use modern libraries like Vue or Angular, probably you’re usin ‘Scooped CSS’, in this case maybe you don’t need to use prefixes like ‘ck-’.

This article was originally wrote in Spanish on my blog.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.