If you’re like the majority of readers, recreating CSS and HTML by reverse engineering might look suspicious to you, and you might wonder what could be the benefits of doing such a thing.

In my opinion, playing with — or recreating — code that interests you, is the best way to learn and to enjoy what you do. The following are some more benefits, some of which most web developers aren’t aware of.

Full WhatsApp Web Reverse Engineering Demo

The Benefits

  • It’s fun!
  • It helps you become a better architect
  • It improves your creativity
  • It shows the potential that the app can reach
  • It proves a concept
  • You can use cutting edge technologies
  • You can advertise yourself
  • It can help you become well-known

My Benefits (Besides Fun😃)

Following my previous article of “Why the World Needs CSS Developers”, I want to show a CSS Developer’s full capabilities. Or, more precisely, in my case, to demonstrate a CSS Architect’s skills, and reinforce them in this way.

Select a Project

When selecting a project to work on, search for a web project that you like. Then, take a brief look to see if this project’s CSS and HTML aren’t well-written.

As you can deduce from the post title, my project is reverse-engineering WhatsApp Web. The reasons I chose it were that first, from my perspective, its non-semantic HTML and CSS class names are challenging to understand, and secondly, the website isn’t fully responsive.

WhatsApp Web’s HTML

How to Start Reverse Engineering

The first important rule, is Don’t Try to Understand the Current Code. Keep in mind that the main reason you’re starting this project is to improve the code. Therefore if you will dig too deep, you risk repeating the very mistakes you are trying to avoid.

Create Semantic HTML

Before writing a single line of HTML, explore the web project as a user. Try to infer as much as you can from the visual structure. After playing with it and understanding it (should take only a few minutes), create the HTML’s hierarchical structure, starting with the main parts and then going into the inner portions.

My basic reverse engineering of WhatsApp Web’s HTML

Notice: I’m using my class name methodology, which I call the CSS Storytelling Methodology, in which the code itself explains the structure’s meaning. It starts with semantic HTML elements and continues with the CSS class-names naming convention.

Other methodologies of this type are the Atomic Design and ITCSS, and my architecture uses some ideas from both, combined with other architecture ideas (for more info on my architecture, you can watch my talk, or read my series of articles).

From the Atomic Design book — parts go from abstract to concrete

Organize CSS

The following might seem like basic advice, but this is something in which most web developers are sinners: One of the most important things in creating good CSS is that it be well-structured. This article will show you how to arrange CSS’s essential parts in a well-structured manner.

Note: In my project on CodePen, I put all the CSS is in one place, even though in real life, I separate the ideas into separate SASS files. There are two main reasons that I changed my workflow on CodePen:

  • CodePen restricts the number of imported files.
  • My way of writing CSS is such that the code is quite compressed, but still easily understood to readers.

The styles go from abstract to more concrete, as demonstrated in Atomic design’s famous example, and shown in the image above.

The Basic of CSS Styles

The above diagram of Atomic Design, although I didn’t read the book, seems to be missing an essential part of the project — the styles that we should write even before starting to create the basic “atoms” parts. We’ll fill in that blank in this section.

Let’s talk about the elemental parts of CSS in a project, the main basic styles which every project should have, but web developers tend to forget.

CSS Resetting

In this project, I used CodePen’s CSS Reset built-in option and added my CSS resets to it for definitions that I felt were missing.

/****** More of My Resets *******/
*,
*::before,
*::after{ box-sizing:border-box; }
button{
   background-color:transparent; color:inherit;
   border-width:0; padding:0; margin:0;
   cursor:pointer; text-align:inherit;
}
img{ display:block; max-width:100%; }

In real life, I use normalize.css to which I add some customized CSS resets. You can read more about how I reset my CSS in my article “Normalize CSS or CSS Reset?!”.

Variables & Variables

Nowadays, besides the SASS variables (or any CSS pre-processor variables), we have native CSS variables, each having benefits that the other doesn’t. For example, CSS native variables work even after the page is loaded (as variables), and we can use them for CSS project-wide colors.

Example:

/* colors */
:root{
  --white:        #fff;
  --dark-gray:    #333;
  --main-gray:    #ededed;
  --light-gray:   #f7f7f7;
  --dark-green:   #009688;
  --info-message: rgba(225,245,254,.92);
}

However, the problem with CSS variables is that we can use them only as property values. Therefore we still want to use the second type, SASS variables (or any other CSS pre-processor variables), for other things, such as creating media rules for responsive design.

/* Responsive Variables */
$break1:     "(max-width:767px)";
$break2:     "(min-width:768px) and (max-width:1023px)";
$break2open: "(min-width:768px)";
$break3:     "(min-width:1024px) and (max-width:1439px)"; 
$break3open: "(min-width:1024px)";
$break4open: "(min-width:1440px)";

Mixin

In this project, I needed only two mixins. The trim text, which is a one-line mixin, and another mixin for scroll style (which has two treatments, one for Firefox(mixin), and the others for Webkit browsers with pseudo webkit styles).

/*mixin*/
@mixin trim{
    text-overflow:ellipsis; 
    white-space:nowrap; 
    overflow:hidden; 
    display:block;
}
@mixin scroll{ 
    overflow-y:auto; 
    scrollbar-width:thin;
}

Note: I created a more complex mixin for trimming text, which can work for multi-lines of text as well. You can read more about it in my article “Trimming Multi-Line Text in CSS”.

Typography

In this section I define the website’s basic typography, such as font-family, font-size, line-height and base text color, if needed for the current project. These are the base styles for our text.

body{
   font-family: Segoe UI,Helvetica Neue ...; 
   font-size: 16rem; 
   line-height: 1.3; 
   color: var(--dark-gray);
}

Besides this, I also use a trick that grants me control of all the font-sizes from one place. I use the rem unit in all font-sizes, with the declaration of font-size: 1px on the root HTML element. This way, font sizes have a ratio of 1rem = 1px, so if I want to increase all font sizes by 20%, for example, I can do so from one place.

html{ 
   font-size: 1px; /* for using REM units */
}

An example of increasing the font-size by 20% for the whole website (in small screens):

/* Small screen */
@media #{$break1}{
    html{ font-size: 1.2px; }
}

For more info on this method, you can read one of my previous articles “Update your font-size to REM units”.

Background Style

WhatsApp’s background design has two colors. In WhatsApp Web, the upper strip is implemented with the ::after pseudo-element. That, in my opinion, is a waste of an element.

Two-color background

How would I solve it? With a linear-gradient!

/* background */
html{
     background: linear-gradient(
         to bottom, 
         var(--dark-green) 1px, 
         var(--dark-green) 130px, 
         #dddbd1 131px, 
         #d2dbdc 100%); 
     background-repeat: no-repeat; 
     min-height: 100vh;
}

Utility Classes

Utility classes are classes that are responsible for one action only. Their properties always get the !important keyword because when you use them, you want those styles always to affect and win the CSS Specificity War. And what if you don’t need those styles? Remove the class from the HTML element!

Note: I got the idea of working with the !important keyword for utility classes from Harry Roberts talk “Managing CSS Projects with ITCSS”.

/* utility classes - always with !important */
.u-flex        { display: flex!important;}
.u-flex-column { flex-direction: column!important;}
.u-margin-end  { margin-#{$end-direction}: 10px!important;}
.u-hide        { display:none !important;}

HTML

<aside class="main-info u-hide">    
     ....
</aside>

Animations

In this CodePen, I used only one CSS animation — one whose purpose is to show the user what is clickable. This animation is aimed at those readers who only see the CodePen and otherwise won’t realize what is clickable.

What’s important is to create a region for all the animations in your project.

/* animation */
@keyframes clickableAnimation {
  0%   {transform: scale(1);}
  95%  {transform: scale(1);}
  96%  {transform: scale(1.5) rotate(-30deg);}
  97%  {transform: scale(1.5) rotate(30deg);}
  100% {transform: scale(1);}
}
.u-animation-click{
  animation: clickableAnimation 20s ease-in-out -17s infinite;
}

Icons — 🕘 💬 🔎 📎 🎤 😃

I tried to use as few assets as possible in my CodePen project because of resource storage issues. Due to that, I thought it would be cool if instead of importing external icons, we’d use the native Emoji icons which all operating systems have nowadays.

<span class="icon">😃</span>

Things might look different on each operating system, but don’t forget that we are only playing — this isn’t a recommendation to use Emojis instead of icons of any type.

On the performance side, The advantage of using native Emoji icons is actually relevant to any project since it’s always better not to have to load fonts from an outside resource.

For accessibility, I applied a CSS filter and transition to the Emojis’ hover/focus state for when the icon nests inside a <button> element, for example:

.common-button{
    .icon{
        filter: grayscale(1) opacity(0.5); 
        transition: 0.2s;
    }
    &:hover, 
    &:focus{       
       .icon{
          filter: grayscale(1) opacity(1);
       }
    }
}

Let’s Talk About Responsiveness

I think most web developers don’t understand the reason for the “mobile-first” invention: Mobile First was invented because the more sophisticated styles usually happen in bigger screens, and therefore it made sense to start the design with the mobile (smallest) screen, whose design was more straightforward and whose styles usually applied to the bigger screens too.

But it seems that this assumption isn’t always correct. Mobile styles aren’t always automatically suitable for the bigger screens — sometimes the small-screen styles are very different from the bigger screens styles.

For that reason, I invented the “Basic First” methodology. Basic First says that only styles that are suited to all media rules will be defined without media query rules. Example:

A reminder for of the media rules variables:

/* Responsive Variables */
$break1:     "(max-width:767px)";
$break2:     "(min-width:768px) and (max-width:1023px)";
$break2open: "(min-width:768px)";
$break3:     "(min-width:1024px) and (max-width:1439px)"; 
$break3open: "(min-width:1024px)";
$break4open: "(min-width:1440px)";

An example of using media rules in a smart way:

.main-header{
/* common style only! for all the breakpoints */

/* mobile & tablet */
@media #{$break1}, #{$break2}{
/*mobile only (from 0px up to 1023px)*/
} 
    /* only mobile */
    @media #{$break1}{
/*tablet only (up to 767px)*/
} 
    /* desktop */
    @media #{$break3open}{
/*desktop only (from 1024px up to infinity)*/
}
}

Just for the fun of it and to show the power of my own “Basic First” methodology, I have added support for smaller screens, which WhatsApp Web didn’t have.

If you want to know more about the “Basic First” methodology, you can read my article “The New Responsive Design Evolution”, or watch my full talk “Responsive Design Best Practices”.

To Summarize

In this post, I tried to show how to create and understand the primary CSS layers we need in a project when reverse-engineering the WhatsApp Web.

By looking more deeply into my code, you can learn more about my HTML and CSS.

About the HTML Part

From reading my HTML, you can learn how to create more semantic HTML and how to give logical CSS class names.

Semantic HTML elements and readable CSS class names

Notice: The sharp-eyed might notice that chats-item-button isn’t <button>. The reason is that when creating this CodePen, I wanted to define the <button> element with display: grid; but that didn’t work because there is a bug in chrome. Due to this bug, I used WAI-ARIA rules (for accessibility) instead.

About the CSS Part

Looking at my CSS/SASS shows how I arranged my project and how I prefer to write CSS. My preferred CSS writing method is to combine several CSS definitions in one line, an idea which most developers don’t like, but maybe looking at my code will help you like it more.

If you want to know more about why I write CSS in one-line, you can read my article “How to Create a More Readable CSS”.

For the other parts of my naming convention, you can just look at my code on CodePen. And as I said before, you can watch my talk, or read my series of articles on CSS architecture.

Final Words

I hope that in this article I gave you some inspiration on how to create the basic styles of a project, and maybe even inspire you to create your own Reverse Engineering projects.

If you like this post, I would appreciate applause and sharing 🙂.

I create lots of content on CSS. Be sure to follow me via Twitter, Linkedin, and Medium.

Also, you can see all of my content on my website: eladsc.com.

Who Am I?
I am Elad Shechter, a Web Developer specializing in CSS & HTML design and architecture.

My Full WhatsApp Web CodePen:

Get more content like this one

I’m starting a new community at CssClass.com.

Signup if you find it interesting 🤓
Articles, open-source projects, and deep-dive into CSS topics.

More content is coming soon at CssClass.com!