How we CSS at EventMobi

Olivier Williams
4 min readDec 3, 2014

Last summer we completely rebuilt our mobile web app. One of the goals of the redesign was to have a modular approach to our CSS.

After seeing the great posts by @mdo, @chriscoyier and @fat detailing how they tackle CSS, I figured we should also share how we CSS at EventMobi.

Our Front-End Stack

We use AngularJS for our front-end JavaScript framework, Stylus as our css pre-processor, and GruntJS as our build tool to put it all together. We use Nib, a CSS extension to Stylus to save us time on a few things like vendor prefixing, gradients and ellipsis.

CSS Architecture

Early on we agreed to keep our CSS as modular as possible. We looked at many different options for optimal CSS architecture, and ended really liking SMACSS. In the end we ended up using a modified version of SMACSS to fit our app, splitting most of our styles based on what template they apply to.

main.styl puts everything together by importing all the other partials in the following order — Globals, Modules and shame.styl.

Shame

shame.styl is a homage to csswizardy’s shame.css. I’ll leave it in his words:

The idea of shame.css is that you have a totally new stylesheet reserved just for your hacky code. The code you have to write to get the release out on time, but the code that makes you ashamed.

All the code in shame.styl (too shameful to share) are hacks that we haven’t had the time to refactor yet. It’s a todo list for how we can improve our code.

Variables

We use variables to normalize our various colors, borders, gradients, etc. A few that have come handy have saved us a lot of duplication:

Colors

We assign variables to color functions, which keeps things really semantic:

// Text
$text-color = $darkergray
$secondary-text-color = $darkgray
$muted-text-color = $gray

This technique enables us to do one color change versus one change in every file.

Gradients

We create a function that outputs the gradient we define. We do this since our version of Nib doesn’t support gradient variables, but this solution actually works really well for us:

gradient-button()
background-color #f5f5f5
background linear-gradient(top, #fff, #e5e5e5)

Which would be used as:

.button
color white
gradient-button()

Functions

We use a few Stylus functions to help cut down on duplicate code across our codebase:

// If text is light (like bright yellow), add a dynamic text-shadow
light-text-shadow(x)
if light(x)
text-shadow 1px 1px 1px darken(x, 60%)
// If text is dark, add a dynamic text-shadow
dark-text-shadow(x)
if dark(x)
text-shadow 1px 1px 1px lighten(x, 60%)
// Word break function for long strings
word-break()
word-break break-word
word-wrap break-word
white-space pre-wrap

Customization

Our customers can change 5 colors to match their brand. In custom.styl we reference every selector that need to be modified by these colors, then we compute the best possible combination using a variety of Stylus functions like lighten(), darken(), rgba(color, opacity).

CSS Stats

CSS Stats is pretty useful tool that we use regularly to see if we’re improving our production CSS. It also serves as a constant reminder as to how we can improve.

Pretty much everything here should be cut in (at least) half.
Spikes = Bad

The Future

We’ve done a lot of legwork to get where we are now, but there’s always room for improvement and refactoring:

Style guide

A style guide would keep CSS more consistent as we add to it. A style guide is a lot of work upfront but will provide a lot of value over time and will make it easier for anyone to read our files.

Better partials

We have a few partial files that we include, but a lot of styles are still lumped together in a base.styl file. We should strive to break down bigger files into smaller chunks.

Resources

If you want to find out more about a process, feel free to reach out to me on Twitter. Here are the articles that inspired this post:

If you’re setting up your app’s CSS architecture, definitely give these a read.

--

--