Skip to content

Modern CSS Architecture

integratorModern CSS Architecture is as I like to say, the integrator’s blueprints.

One of the reason why I’m saying this is based on the fact that every integrator has it’s own style and this style is being build based on it’s own experience. One of this article’s scope is to get those common elements and see what we need to focus on and what are the things that makes a CSS structure stable, better and scalable.

Either if CSS3 might look very simple, is actually not that simple as it seems. Chris Eppstein was saying where I want to get and to talk about:

‘CSS is simple… It’s simple to understand. But CSS it’s not simple to use or maintain’.

When we’re creating our structure, all looks very pretty (like an empty room after you’ve painted it). Unfortunately very often, after we’ve struggle and completed our project, the CSS structure will look like hell (most of it I can say it’s looking like a room where you’ve deposit all you stuff without any logic order).

We might ask ourself what means to write a good CSS code. The answer is very simple:

  • Write functional CSS code. It actually represent to write a CSS class name based on it’s purpose;
  • Write code without tables and less images as possible. Tables are good when we need to add some complex structure of dates, but not when we need to arrange our content and use the amount of images as minimal as possible. To optimize this we can use image sprites, svg and many other tricks.
  • Use the latest methods of CSS3. Browsers are up to date now and we can use transition, transform and all the new elements which CSS3 has provided us.

We also need to put ourself some questions before we are starting to write some code: Is it readable? Is it easy to change or extend? Is it modular or scalable? Is it independent of the other parts of our DOM elements? If not, then we might get some troubles in the future, and because of that we need to clarify some things for our application style.

 

The Goals of a good CSS Architecture are:

  • Predictable. Your rules should act as you want them to act. It should not affect any parts of your site unintended when adding / removing / updating some other rules.
  • Reusable. Use abstract and independent rules so you can quickly build new components whenever we need and avoid resolving problems that are already fixed.
  • Maintainable. You shouldn’t refactor our current style when we add / update some element / component.
  • Scalable. Your site CSS Architecture is easily approachable by a large team and a large amount of information.

 

The common ‘Bad Practices’

Common solutions might be bad practices even if they are techically valid. Let’s take some example of this bad practices and let’s try to avoid them. We’re going to come with some suggestions of what is good in the last part of the article.

  1. Modifying components based on who their parents are is a very common bad practice used.
 .btn{
 background: yellow;
 border: 1px solid black;
 color: black;
 width: 50%;
 }

#sidebar .btn{
 width: 200px;
 }

body.hompage .btn{
 color: white;
 }

Almost all apps have sections with common elements, except one.

  • It’s not predictable (several buttons used in different location might look different despite same markup);
  • It’s not scalable or reusable;
  • For new look on homepage, new rules will be added;
  • Not maintainable
  • It’s violating the open/close principle of software dev.

We need to take count of Bertrand Meyer’s advice:

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification’.

 

2. Try to avoid complicated selectors. This is based on the common desire of get a clean HTML DOM.

#wrapper section h1:first-child { ... }
#articles > section > h3 + p { ... }
#navigator ul li a ul li:before{ ... }
  • Not reusable
  • Not predictable
  • Not maintainable or scalable when the HTML changes

3. Making a rule with too many propertiesThis makes referince to the nesting of properties with different purposes. It’s a bad pratice to add width and color to a box, because we might need the same property in other ocasion and we’re avoiding code duplicates.

 position: absolute;
 top: 20px;
 left: 20px;
 background-color: red;
 font-size: 1.5em;
 text-transform: uppercase;

Ok, but you are going to ask me… How should I do it?

 

SOLUTIONS

  • CSS should be just a set of visual elements and not be mixed with other purposes;
  • Think outside the box and never use a class just for one time use;
  • Components that must look different should be defined different and HTML is responsible to call them;
  • CSS has to know as less possible as he can about HTML structure.

To respect this, we can define for example a component with the .button class. If HTML needs an element to look like this, it should call it. If there are some places where the style of this one changes, then that style has to be defined into another element called modifier and the HTML will just include it in the previous class to complete the new look.

 

The BEST PRACTICES

1. Be intentional which means to don’t allow the selector to have unwanted style by using a sniper and not a grenade

 /* Heavy grenade */
 #nav ul li ul { ... }

/* Thin sniper*/
 .subnav { ... }

2. Modulate your concern by avoiding nesting background, color, font properties with position, width, height and margin.

3. Namespace your classes

Parent selectors are not very efficient, that’s why it’s a good solution to add to the subelements the parent class. Is minimizing confusion and makes components more modular, either it might looks verbose.

 /* A big risk of style cross-contamination */
 .button { ... }
 .button .icon { ... }

/* A small risk of style cross-contamination */
 .button { ... }
 .button-icon{ ... }

4. Use modifier class when we need a component to look different into a different context. We should use this instead of nesting and attaching it to the parent.

/* Bad practice */
 .button { ... }
 #sidebar .button { ... }

/* Good practice */ 
 .button { ... }
 .buitton-sidebar { ... }

5. Define the purpose of every class. Classes are used for: style, JavaScript handling and for many other feature detection. We get a big AFRAID of deleting a class because we do not know what are used for in some cases. For this, we should create different classes which defines each purpose.

  • .js-button – For JavaScript handling
  • .supports-button – For Modernizr classes
  • .button – For style and only for style

6. Name your classes with logical structure. Let’s have and example where the CSS is written using a lot of hyphens and words. This is not enough to identify our elements.

 /* A component */
 .button-group { ... }

/* A component modifier (modifying .button state) */
 .button-primary { ... }

/* A component sub-object (lives within .button) */
 .button-icon { ... }

/* Is this a component class or a layout class? */
 .header { ... }

It looks nice, simple and elegant. But what are every element purposes and what they represent? We can not know for sure. That’s why, we use naming conventions that will help us to know exactly the purpose of every item.

 /* Component Rules */
 .component-name { ... }
 .component-name--modifier-name { ... }
 .component-name__sub-object { ... }
 .componenet-name__sub-object--modifier-name { ... }

/* Layout Rules */
 .l-layout-method { ... }
 .grid { ... }

/* State Rules */
 .is-state-type { ... }

/* Non-styled JavaScript Hooks */
 .js-action-name { ... }

As a conclusion we can write a very beautiful CSS code if we are consider the above advices. Enjoy and i hope they will easy your work.

 

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *