Building front-end apps that are styled for the ages

Subbu Swaroop
Freshworks Developer Platform Blog
8 min readJan 17, 2021
Writing Clean css header image
Write less to do more

We live in a fast-evolving world, so it is important that we evolve along with it. It has been more than 25 years since the first release of CSS on December 17, 1996. At the time of writing this article, the latest version of CSS is CSS3. Compared to its predecessor, CSS2.1, CSS3 brings a lot of new features to the table such as animations, box-sizing, media queries, and a function named “calc()” which can be used to make arithmetic calculations. We can be optimistic that we will be seeing many more such cool features in the upcoming versions.

As a developer myself, I must confess that most of us often write CSS to just get the job done. It isn’t uncommon for one to refer to open source forums like StackOverflow or CSS-tricks which provide instant CSS snippets that can be copy-pasted into one’s own code. However, much of the CSS that we borrow from these forums was probably written several years back, some of it even before CSS3 was introduced! While they might work very well, there’s no guarantee that they follow best practices and give a better performance compared to the ones that were written following the latest CSS standards. This often reminds me of a quote I like and always have in my heart. It was written by Robert C. Martin, colloquially called “Uncle Bob”, in his book “Clean Code: A Handbook of Agile Software Craftsmanship

Clean code always looks like it was written by someone who cares.

In the same spirit, today we will be looking at best practices around the use of CSS like writing cleaner code, following predominant UI standards, and scaling the code base for bigger apps. These are derived from simple but effective practices we follow at Freshworks ourselves.

Move CSS to separate files

It’s a fact that inline CSS and those written inside <style></style> tags are much more performant than those saved in a separate file. This holds true even when we are building a Freshworks app. Once we start adding more features or making changes to existing ones, this starts to become an inconvenience as it results in having redundant CSS in many places while making overriding them literally impossible.

It is therefore a good practice to have separate CSS files for different modules in an application, rather than dumping them in a single file. This additionally helps in avoiding the inclusion of unnecessary CSS that should also improve page load speeds.

Use custom font sizes and colors

Normally, when we want to insert a heading, we use one of the heading tags ( <h1>, <h2> … ). They each have a different font-size and font-weight associated with them. It’s easy to use one of these depending on the use case, but sometimes when we want a bigger heading, the default properties might not be enough. That’s when we should choose custom font sizes.

Let’s take one of the apps on our Marketplace — “Stripe by ChargeDesk” — as an example. This app gives you access to your Stripe payment data where it’s most needed — in the context of an agent’s conversation in Freshchat.

Stripe by ChargeDesk
Custom font sizes and colors in action

Here, the amounts “2 X $15.99” and “$30.00” are bigger and bolder compared to the other texts. This is done to emphasize the important data, which in this case represents the monthly charges. While these styles can be achieved using any of the <h1> or <h2> tags, we need to avoid them here since their purpose is to define headings and subheadings respectively. We can instead achieve this by using a <span> tag with custom CSS properties.

We can also note that different colors have been used for the buttons “refund” and “cancel”. This makes the user aware of the actions since colors play a vital role in good design. We encourage you to learn more about call-to-action colors to make your app experience more intuitive.

Avoid float for column layouts

If you have been working with CSS for a long time, then you would have used the “float” property very often, especially when aligning an element to the left or right of another element. While floats do more than that, sometimes it’s better to look for an alternative. One such use case is when defining multiple column layouts. Let us take a simple 3 column layout like this:

A simple 3 column layout

This can be achieved in two ways. The first one is by using the float property and specifying the width for each of the divs.

The legacy way of using floats

The second one is by using the CSS3 flexbox’s flex property on the parent div and then specifying the flex-grow property on the child divs.

The new way of using flex

Flexbox comes in handy when we add responsiveness, which is very important for any web/mobile apps. Let’s take our Custom-Installation-Page_Omni app as an example.

Custom-Installation-Page_Omni
A layout achieved using flex

Since this is a full-page app, this layout can easily be achieved using CSS flexbox. When viewing the same on smaller screens, we can make the fields stack on top of each other just by changing the “flex-direction” property like below.

Flex vs Floats

We can clearly see why flex is the winner here. Another great thing about flex is that they are supported by all major browsers including Internet Explorer 11.

Use CSS3 variables

When building complex apps, we often have large amounts of CSS with values repeated in so many places, especially in the case of colors and fonts. This makes it difficult to replace a specific color or a font across the entire app when a change is required. How do we avoid this without using Javascript variables?

CSS can do wonders

Yes! We can use custom properties to store values and reuse them wherever we want using the CSS3 var() CSS function.

Use CSS3 variables for better code maintainability

A best practice is to define custom properties in the :root pseudo-class at the top of our stylesheet file. The variables defined inside them will be available for all the HTML pages in which the stylesheet file is included.

Use Shorthand properties

Shorthand properties are used to group multiple CSS properties that are related to each other. They help in reducing the number of lines of CSS and give a clean look. While they are clearly beneficial, they also have some tricky edge cases which we should be aware of. A list of all shorthand properties can be found here.

Shorthand properties in action

Group selectors with similar CSS

Selectors are used to target a specific element or a group of elements that has similar CSS. When an application becomes big, so does the code and we tend to copy-paste similar CSS in many places. Due to this, there are chances that the same CSS will be used inside different selectors and duplication might occur. To avoid this, a good practice is to identify the selectors that have similar CSS, group them and define them at the top of the file.

Grouping selectors might not be called for when the application is still very small. But once we start adding more components and those components start to use similar CSS, we can opt for grouping them into one.

An example of grouping selectors

Choose selectors wisely

Specificity, if not handled properly, becomes a major problem for developers when writing CSS. When two or more conflicting rules point to the same element, then the rule with the higher specificity is applied to that element. This becomes harder to handle when we have nested elements.

For example, let us take the sentimental-jeff app from our sample apps repository.

Specificity in play with the sentimental-jeff app

We can see that an id selector “sentimental-jeff” is used here because we know that this element will not repeat itself and will always be unique. In such cases, it’s okay to use an id selector. We have also used a class selector “emoji” in the child element since we will have a different emoji for different sentiments and it will be easier to override their CSS when a class selector is used.

Another advantage of using class selectors is that they can be easily extended to create other class selectors and they can be grouped together easily. In such cases, a best practice is to use class selectors for child elements rather than using element selectors or id selectors. This helps to avoid confusion and also reduces specificity-related problems.

Add comments for the complex parts of your code

While this is something that is easily overlooked, it’s a good practice to add comments for the parts of your code that are harder to comprehend. This is especially important for the code that we think will be revisited in the future. Let us take an example from the imposter-checker-app code in our sample apps repository.

Are the styling choices here obvious?

For an experienced developer, it might be easier to understand what this CSS does. But for a beginner who has just started learning flexbox and grid layouts, this could be overwhelming. Adding a short description of what it does and where it is being used would be helpful.

Opt for a design library

So, what is a design library? It is a collection of pre-built components that offers control and flexibility to build rich interfaces. Basically, they help with creating cool UI elements faster and easier. One such library is our very own Crayons. It was developed mainly to support developers who build apps for the Freshworks platform.

Crayons offers a bunch of pre-built components that you can directly plugin to your app. Let’s say you want a text field with icons and validation messages. Rather than building these components yourself, you can use the Crayons input component which does the job for you.

Crayons Input text field and its validations

When it comes to styling your app for the win, this is just the icing on the cake 🍰. You can also check out the official Crayons documentation to learn how to use this with your next app.

Conclusion

It’s always harder to go back to code we have already published and implement some of these practices. Yes, we all know why that is the case 😉

But it’s certainly easier to follow them going forward, especially when you are starting to deal with larger and more complex apps with more than a thousand lines of CSS. We use these practices ourselves at Freshworks and certainly hope and wish some of these practices will stand the test of time and serve you well too. Let us know what you thought of them; we would love to hear from you!

Follow us on Medium to get regular updates on our blogs. You can also reach out to us at the developer community forum for further queries or suggestions.

--

--

Subbu Swaroop
Freshworks Developer Platform Blog

Full-stack developer at Freshworks| Blogger | Fitness Freak | Motivator | Optimist | Ambivert | Anime Fan