DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. Languages
  4. CSS refactoring

CSS refactoring

Giorgio Sironi user avatar by
Giorgio Sironi
·
Sep. 28, 10 · Interview
Like (0)
Save
Tweet
Share
7.74K Views

Join the DZone community and get the full member experience.

Join For Free

It's quite easy, when jumping on the CSS bandwagon, to start using complicate selectors in every angle of the stylesheets, and to disseminate our (probably generated) markup with classes and ids with the goal of a finer selection.

But here's the news: CSS are composed of code. Unless you use CSS preprocessors or PHP-based stylesheets, it is mostly declarative code, and it is usually present in a fairly small quantity with regard to the Java, Python, PHP or HTML code of the same project.

However, without proper maintenance every kind of code is prone to the same corruption: duplication, lack of simmetry and encapsulation, leaky abstractions.
In this article we'll see an example of refactoring of a small set of CSS rules to address their smells. Clean code saves you time and money, and this is true also in the realm of CSS files, which can grow to thousands of lines long.

Smells and testing

For starters, note that there is a inherent coupling between the markup (HTML and PHTML or JSP files) and the CSS selectors you're using. As so, refactoring one of them means changing the other.

We'll initially focus on finding smells in our CSS code and on trying to eliminate them. We haven't got many tools at our disposal - such as classes and methods - but many situations can be improved.

In our example, the refactoring targets are:

  • duplication of code, in every form; selectors and rules.
  • overspecification, when the selectors are too precise.
  • fake abstraction, when the selectors names include physical characteristics.

Unfortunately there are no automated testing frameworks for web design (are they?), so we should rely on a manual test. These frameworks may be possible to buidl by simply taking snapshot of pages viewed during Selenium tests and checking the disposition of elements and color. However, this approach is very brittle and a test would break every time a design trait is changed, even for a 1 pixel difference.

Snapshot 1

Let's start with the code. The example consists in a small menu built with divs.

<style>
div.menu
{
    float: left;
    width: 80px;
    padding: 1px;
    border: 1px solid gray;
}
div.menu_item
{
    float: left;
    width: 80px;
    background-color: gray;
    margin-top: 2px;
}
a.menu_blue_link
{
    color: #003366;
    text-decoration: none;
}
br.clear
{
    clear: both;
}
</style>
<div class="menu">
<div class="menu_item"><a class="menu_blue_link" href="/">Home</a></div>
<div class="menu_item"><a class="menu_blue_link" href="/contacts">Contacts</a></div>
<div class="menu_item"><a class="menu_blue_link" href="/portfolio">Portfolio</a></div>
<div class="menu_item"><a class="menu_blue_link" href="/prices">Prices</a></div>
</div>
<br class="clear" />

We are going to perform the following operations:

  • change the markup to a more semantic one. Divs are used too much nowadays, given their generic feeling.
  • omit declaration of elements from selectors since the are already pretty unique (removing overspecification from the picture, so that we can change the divs to other elements many times without touching the CSS anymore.)
  • change the names menu_blue_link to menu_link; this is a form of leaky and unuseful abstraction: what if we change the color? We would end up being forced to change also the CSS class to avoid a green menu_blue_link. The same would be done for the infamous <div class="right">.

Snapshot 2

 

<style>
.menu
{
    float: left;
    width: 80px;
    padding: 1px;
    border: 1px solid gray;
}
.menu_item
{
    float: left;
    width: 80px;
    background-color: gray;
    margin-top: 2px;
    list-style-type: none;
}
.menu_link
{
    color: #003366;
    text-decoration: none;
}
br.clear
{
    clear: both;
}
</style>
<ul class="menu">
<li class="menu_item"><a class="menu_link" href="/">Home</a></li>
<li class="menu_item"><a class="menu_link" href="/contacts">Contacts</a></li>
<li class="menu_item"><a class="menu_link" href="/portfolio">Portfolio</a></li>
<li class="menu_item"><a class="menu_link" href="/prices">Prices</a></li>
</ul>
<br class="clear" />

Now the situation has been improved a bit, but we have more work to do:

  • we can inline a class that reveals itself with its name: clear. It occurs only on a <br> and while it is a de facto standard to use classes named clear, I argue that they are a leaky layer of abstraction too.
  • We can also use containment selectors to unify the various .menu* classes.
  • We introduce the trade-off of using the tag <li> in the relative CSS selector instead of the class. However now we'll have one class less to refer to in the markup.
  • menu_link would be ever applied only to an a element, so it would be wrong to abstract it away (underspecification): we'll just refer to it in the selector.

Snapshot 3

 

<style>
.menu
{
    float: left;
    width: 80px;
    padding: 1px;
    border: 1px solid gray;
}
.menu li
{
    float: left;
    width: 80px;
    background-color: gray;
    margin-top: 2px;
    list-style-type: none;
}
.menu a
{
    color: #003366;
    text-decoration: none;
}
</style>
<ul class="menu">
<li><a href="/">Home</a></li>
<li><a href="/contacts">Contacts</a></li>
<li><a href="/portfolio">Portfolio</a></li>
<li><a href="/prices">Prices</a></li>
</ul>
<br stye="clear: both;" />

Now we have a much cleaner markup, which shows its semantic properties with the list elements, and a CSS ruleset with a reduced amount of duplication (for what we can accomplish without imperative code).

Conclusions

This isn't rocket science, and I trust you knew many of these tricks already; but applying the principles of clean code in any situation, even graphic design, is the difference between the novice and the craftsman.

CSS

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Spring Boot vs Eclipse MicroProfile: Resident Set Size (RSS) and Time to First Request (TFR) Comparative
  • Kubernetes-Native Development With Quarkus and Eclipse JKube
  • How To Handle Secrets in Docker
  • A First Look at Neon

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: