The evolution of effective CSS writing

Source See NYC's Changing Skyline at New Skyscraper Museum Exhibition - Untapped New York

How do you work effectively with CSS so that you feel comfortable with every modification? In this article, you will find a very brief overview of the development of CSS writing and description of the most common problems.

Table of Contents

  1. A little history
  2. What came before CSS?
  3. The arrival of CSS
  4. Problems with properties of CSS
  5. Methodologies and architectures
  6. Wrapping up

A little history

In 1994, Håkon Wium Lie realized that there was a need to create a language that would create ways to visually edit documents on the web. The main idea was based on the need to separate the content from the presentation. Lie, together with other designers, created the first version of CSS, which over time was implemented by all browsers. After HTML, CSS became the second standardized language for W3.

This archived e-mail communication shows the origins of the idea of visual editing of HTML documents. As you can see, after pasting the same HTML, the content was displayed differently on two different browsers (Netscape and Mosaic). The developers of the Mosaic browser decided to add an indent from above before the list (now known as an unordered list). They just thought it would look better. Everyone then perceived it as a bug and this resulted in the need to have control over how their content appeared on the web.

Source Wikipedia

In the mid-1990s, when the first websites began to appear, differentiating from the default browser display settings was a real challenge. At a time when cascading styles were still being tested, it was only possible to modify the design using HTML attributes. However, the first web browsers like ViolaWWW did not allow you to adjust the visual appearance almost at all.

What came before CSS?

In the 1990s, website designers began to make the first attempts at what we now call web design. A common example of a 90's site is the Space Jam site. The site of the famous WarnerBros animated film is still online in its original state after 24 years; it is still possible to go through and explore it.

It is interesting to see on this website how color and text differentiation was approached in this era and how the layout was organized.

All colors are defined in the body of the page, where the creators set the basic rules for the display using HTML attributes. Specifically, the attributes bgcolor, text, link, vlink and alink. The attributes defined in this way then made it possible to display the colors of texts, links, and backgrounds differently.

Another nice example on this site is the layout. At the time, it was modified only with the help of one or more embedded tables. This technique was then used for several more years to create all web document layouts.

First for the circular layout at the time (example of the Space Jam website) and then for the Holy Grail Layout, which has been a trend in web design for many years. This spreadsheet technique is still recommended today for creating newsletters and PDFs generated using HTML, because many e-mail clients simply did not choose to change their systems.

“Code newsletters like it’s still 1999”The Understanding Group

This example shows how designers came to the result of this circular layout, which was popular at the time. Companies wanted to differentiate themselves from the competition, and so the first attempts were made to change the default visual settings.

Placing images in a circular layout was then achieved again using the attributes of tables - specifically align and valign- and also using the HTML tags br. This was the basis of web design for several years.

The arrival of CSS

The advent of cascading styles was revolutionary at the time. In 1998, Eric Meyer and his team began to describe how it is possible to implement and use cascading styles. Over time, CSS made its way to the first website and soon became the standard for website design.

   font-family: serif;
   background-color: silver;
 H1 {
   font: x-large Verdana, sans-serif;
   color: olive;
   border-bottom: thin black solid;
   margin: 0;
 .sidebar {
   background-color: olive;
   padding: 0.5em;
 .sidebar UL LI {
   list-style-type: none;
   margin-left: 0;
   margin-right: 0.5em;
 .sidebar UL LI A {
   color: #ffcccc;
 .body {
   background: white;
 IMG.icon {
   border: outset gray 3px;
   padding: 0;
 P {
   margin: 0em 0.5em;
   text-indent: 1em;

In the beginning, it was a great revolution. There was no need to rewrite the attribute values on all pages to change the title color; one small change in cascading styles was enough. This was a great time-saving breakthrough for developers everywhere.

“Two CSS properties walk into a bar.
A barstool in a completely different bar falls over.”Published on the community site

Developers started using CSS more frequently, but few had addressed the need to organize and maintain styles in any way. Writing CSS without any organization or idea for sustainability was no longer enough.

There were no ways to maintain cascading styles and manage the often inconsistent design of large sites (which in some cases continues to this day). Thus, complications began to arise.

Problems with properties of CSS


What complications can arise when writing CSS? Writing CSS can be a tough nut to crack, especially for beginners. On the one hand, cascading styles are very easy to understand due to their straightforwardness, but on the other hand, they are quite complicated to maintain, modify and structure. Many problems can occur. I will try to briefly describe some of them.

High specificity

Everyone who has ever worked with CSS has certainly encountered this problem. The developer receives input from the graphic designer, considers which HTML element could be used, and starts writing the selector. Developer decides to use an unordered list from which he wants to create a list with blue link colors and a font size of 20px. He will use simple selector.

Then he inserts HTML into the codebase - deep into the structure of the web, where it belongs and where it should be displayed.

Then he writes the following CSS:

.list li a {
    font-size: 20px;
    color: blue;

This is not the result he wanted. The links are red, the font is 16px and bold. He looks at DevTools and finds that the selector is already overridden by another selector that prevents the correct result from being plotted:

body #content .page ul li a {
  font-size: 16px;
  color: red;
  font-weight: bold;

What option does the developer have now? All that remains is to increase the specificity of the newly-created selector, modify the overridden selector or use !important. Of course, there are more possibilities, but in principle it is still a struggle with specificity.

Very few people make adjustments to an already-finished selector, and we know why not to do so. There is no choice but to increase the specificity by adding a .list class to our unordered list.

body #content .page ul.list li a {
  font-size: 16px;
  color: red;
  font-weight: bold;

This creates a new selector in a fixed location that can no longer be used. If you need to use it elsewhere, you have to add another piece of code.

Nesting hell

Most developers rarely realize that CSS can be used to design web documents and applications. With the advent of the popularity of preprocessors, the writing of cascading styles has become a bit closer to a programming language (thanks to the possibility of using variables, cycles, or mixins, for example). Preprocessors also came with one novelty, and that was the immersion of selectors into each other.


The deciphering of such code and its subsequent modifications was thus in some cases almost impossible. The following code looks threatening, but it's nothing special, and we often come across something like this when refactoring CSS.

.Checkbox--toggle {
  .Checkbox {
    &-input {
      &:checked {
        & + .Checkbox-label {
          @extend .Checkbox-toggle—active;
      &:not(:checked) {
        &:focus {
          & + .Checkbox-label {
            &::before {
              background-color: $checkbox-toggle-active-bg;
      & + .Checkbox-label {
        background-color: $checkbox-toggle-active-bg;

What will the resulting compiled selector look like? I did not dare to publish the result of this selector, but from the following picture you can get an idea of what such outputs look like.

.Checkbox--image .Checkbox-input:checked + 
.Checkbox-image .Checkbox-toggle,
.Checkbox--image .Checkbox-input:checked +
.Checkbox-image .Checkbox--toggle .Checkbox-label,
.Checkbox--toggle .Checkbox--image .Checkbox:checked +
.Checkbox-image .Checkbox-label,
.Checkbox--toggle .Checkbox-input:checked + .Checkbox {
  background-color: #71C5E8; 
.Checkbox--image .Checkbox-input:checked +
.Checkbox-image .Checkbox-toggle::before,
.Checkbox--image .Checkbox-input:checked +
.Checkbox-image .Checkbox--toggle .Checkbox::before,
.Checkbox--toggle .Checkbox--image .Checkbox:checked +
.Checkbox-image .Checkbox-label::before,
.Checkbox--toggle .Checkbox-input:checked +
.Checkbox-label::before {
  background-color: #0284FF; 

Such immersion of selectors do not allow such code to appear in the preprocessor file or in the resulting CSS and should be avoided.

It is good practice to use selector plunges up to the second level. In some situations, they can be used up to the third level. Then the code will be easy to read and won’t cause endless headaches.

.button {
  padding: 10px;
  @include breakpoint(tablet) {
    padding: 8px;
  &:hover {
    background: blue;
  &.is-active {
    color: red;
  &-icon {
    max-width: 16px;
  &-text {
    font-size: 0.875rem;

Such code is then easily readable. The developer can immediately understand what is happening, how he can further expand the record, and how he can work with it.


The order matters. Another typical mistake when writing CSS is to ignore the fact that we have to pay attention to the order in which we write selectors. This feature of CSS discourages many developers from engaging in and developing styles because they simply do not understand and cannot deal with these features.

Source Combining the Powers of SEM and BIO for Improving CSS

Methodologies and architectures

To address the inherent complexity of CSS, various types of best practices and techniques have been introduced to help you create meaningful, sustainable, and extensible code for the design of your websites and applications.

For most web design needs, there is more than one way to approach a problem. There are four methods that stand out among others when considering how to structure code and name classes.


In 2008, Nicole Sullivan borrowed an object-oriented design concept to provide structure to CSS. She presented her OOCSS concept at the Web Directions North lecture.

From OOCSS Web by Nicole Sullivan

In short, this methodology defines a CSS object as a visual pattern that can be used throughout the site. It serves as a guideline when designing reusable code that is more editable and sustainable.

OOCSS has several rules that must be followed. However, this methodology is based on two rules.

Department of appearance and structure

This rule means that you never put HTML elements in selectors. In the event of a change, the code must then be modified in two places.

/* This is not allowed, it create HTML dependency */
.product-detail h2 {}

/* This is good approach, there is no HTML dependency */ .product-detail-heading {}

Content and container department

This rule says that you should write selectors, regardless of the location on the page, to make them as useful as possible across the web document. In fact, it tells us to simply avoid the following selectors:

/* This is not allowed, there is page location */
.hero .heading-secondary {}

/* This selector also break the first rule */ .page-detail h2 {}


Scalable and Modular Architecture for CSS is a methodology and book of the same name by Jonathan Snook. The main idea of SMACSS is to categorize the CSS rules system.

From SMACSS Web by Jonathan Snook


This category includes basic settings for HTML element rules. This includes standardization and basic settings.

body, form {
  margin: 0;
  padding: 0;
a {
  color: #039;
a:hover {
  color: #03F;


This layer includes dimensional declarations.

#header { … }
#primarynav { … }
#maincontent { … }


This is a layer for what we call reusable components. Declarations of buttons, sidebars, menus, etc. can be found here.

.module > h2 {
  padding: 5px;
.module span {
  padding: 5px;


A state is something that augments and overrides all other styles. These are JavaScript dependencies that can apply to layout and/or module styles too.

.is-tab-active {
  background-color: white;
  color: black;


This layer is optional and belongs to a separate file. This is a list of rules that change the visual appearance if you want to create a different identity for your application.


BEM is a methodology for writing CSS, backed by developers from Russian corporations. BEM stands for Block Element Modifier, which summarizes the naming convention used and the overall approach to the organization.

Image by Jed Lehmann from article “Why your CSS needs BEM

The main benefit of this naming convention is that the selectors of the lowest specificity are created, and due to the uniqueness of their naming, no conflicts arise. BEM is also practical to use when working on a larger team of developers because its structure is simple and easy to understand.

Image from article “How does BEM make your life easier” by Alex Daughter

There are many articles on the BEM methodology, but I recommend the article Combining the Powers of SEM and BIO for Improving CSS, where author Ryan Yu describes the problems with the basic BEM notation.


ITCSS, or Inverted Triangle CSS, is an architecture created by Harry Roberts that helps organize CSS files according to certain rules. Thanks to ITCSS, you can achieve the correct classification, which allows you to write meaningful and long-term sustainable style sheets.

This style organization is best suited for work on larger projects and also for working on a team where more developers write CSS. The structure itself requires other principles and methodologies to function, but as a basis for good maintenance of files, is excellent. That being said, this architecture also works on even the smallest projects and makes sense to use anywhere.

From article “ITCSS: Scalable and Maintainable CSS Architecture” by Lubos Kmetko

The basic idea is to rank selectors according to a specificity that less experienced developers often struggle with. The structure is divided into 7 categories according to specificity and can be expanded and modified as needed. The basic division in the project can then have this structure:


Space for preprocessors with variables such as colors, design tokens, typography, grid.


Layer with mixins, functions, media queries.


Here we insert styles for third party libraries such as normalize, reset or any others


Selectors for bare HTML elements such as h1, p, article, a.


Class definitions for layout, grid, indentation - reusable non-decorative styles.


Specific components across the project - accordion, buttons, breadcrumbs, tooltip.


Class utilities that are designed to affect one particular CSS property and are in most cases written with the utmost importance. Utilities and helper classes with ability to override anything which goes before in the triangle.

This methodology is much more thorough and I recommend studying it before using it. Many people understand this organizational structure inaccurately and will lose the huge benefits that ITCSS offers.

Wrapping up

CSS has undergone a long development and thanks to continuous improvement (from the most experienced developers in the field) it still manages to improve and develop its functionality and capabilities. It thus holds a stable position next to its competition for the development of web documents and applications.

With the right methodologies, architectures, and good language skills, you can create structured notations that are easy to write, maintain, and extend.

Back to Top