Posts by Fabio Yamate

CSS preprocessors like SASS and LESS improved the way we write CSS nowadays. It provides better ways to organize styles into files, that can represent a component or page, and then compile into a single file, following the idea of reducing HTTP requests. Also there are other features like variables, mixins and placeholders that help with code reuse and maintenance.

However, it is possible that with the growth of your application code base the number of CSS styles will surpass the limit rules supported by IE9 or above. The current limit is up to 4095 rules per file.

But it is good to note that only the overflowed styles will be ignored. So, considering this detail, you might take some time to figure out that your layout is broken unless you are aware of this issue, since other browsers like Chrome, Safari and Firefox does not have such limit.

The simplest way to fix that is to split your main stylesheet into multiple files. Using a pre-processor makes the job easy, just create another manifest and move some imports to the newest one and problem solved.

Easy, huh? Well, if you have a well organized CSS the job might be straightforward, but if you don’t, you may struggle with some difficulties.

Here are some experiences that we got when addressing this issue.

Prefer to use placeholders instead of classes

We had some CSS styles that used @extend .some-class and it caused some problems as the .some-class definition is written to the CSS file, even if it is never used. One options is to convert classes into placeholders so they can be reused without being generated.

To make matters worse, .some-class was often defined in another file, which led to the file being imported, duplicating its rules over different files. This takes us to our next tip.

Organize variables and mixins into separated files

As your codebase grows, it is possible that variables, mixins or placeholders get spread in different files. So, if you have to split a CSS file, or even reorganize it, you will have to carefully ensure that all variables, mixins and placeholders are ported over. Keeping them in their proper files like _variables.scss and _mixins.scss cleans up the code and makes future refactoring much easier.

Use tools to break the compiled CSS file

There are projects that try to address the problem of long CSS files using a CSS parser to count the number of styles and generating multiple files when necessary. It is another solution to be aware of, but if you have a well organized CSS structure and guidelines to keep them clean, you can achieve the same result without adding another dependency or step in your asset pipeline.

Ways to detect the number of styles

From the command line

$ curl --silent <url> | grep -o '{' | wc -l

or if dealing with a compressed asset

$ curl --silent -H 'Accept-encoding: gzip' <url> | \
> gunzip - | grep -o '{' | wc -l

For example:

$ curl --silent http://plataformatec.com.br/stylesheets/all.css | \
> grep -o '{' | wc -l
339

Another easy way is just opening the CSS file in your browser and search for {.

Note that if you want to check the resulting CSS file in development you need to enable assets concatenation. One options is to set config.assets.debug to false in your development.rb file.

Summary

Preprocessors help a lot but it also requires discipline like any other code that you write. If you need inspiration to organize your files, you can take a look on Bourbon and even the well known Bootstrap project.

Do you know any other cases where a well structured CSS saved you?


We have been working in a project which deals with date events and we needed a recurrence feature in the application. An initial implementation could simply work with Rails ActiveSupport and use its Date helper methods, in order to shift by day, week, month and others.

>> Date.today
=> Thu, 15 Apr 2010
>> Date.today.next_month
=> Sat, 15 May 2010
>> Date.today.next_week
=> Mon, 19 Apr 2010
>> Date.today.next_week(:thursday)
=> Thu, 22 Apr 2010
>> Date.today.advance(:days => 4)
=> Mon, 19 Apr 2010

Very easy, right? But what if we now want events that occur every monday or sunday? Or events that happen at each two weeks? For each new case, we will need to add and deal with more and more logic.

Instead we have been using the Recurrence gem, created by Nando Vieira with some contributions by José Valim (yeah, our good fellow ;)). Recurrence works with ActiveSupport as its base for date calculation and provides a simple DSL to work with recurring events. Let me show a simple example:

# events every day, considering today as Apr 15th.
>> r = Recurrence.new(:starts => 2.days.ago, :every => :day, :until => Date.tomorrow)
>> r.events
=> [Tue, 13 Apr 2010, Wed, 14 Apr 2010, Thu, 15 Apr 2010, Fri, 16 Apr 2010]

If no :until is determined, it runs until year 2037 (maybe the end of world? No, it’s when the unix time 32-bit overflow…). You can check the Github repository and this blog post (in brazilian portuguese) to learn different use cases and examples for Recurrence.

Now I want to show you how we integrated it with our application. We have built an EventRecurrence class which deals internally with the recurrence logic.

# app/models/event_recurrence.rb
# It has :start_date, :every and :end_date as database columns
class EventRecurrence < ActiveRecord::Base
  def dates(options={})
    options = {:every => every, :starts => start_date, :until => end_date}.merge(options)
    options[:on] = case options[:every]
    when 'year'
      [options[:starts].month, options[:starts].day]
    when 'week'
      options[:starts].strftime('%A').downcase.to_sym
    when 'day', 'month'
      options[:starts].day
    end
    Recurrence.new(options).events
  end
end

Notice we need to setup the options hash for different cases (day, week, month and year) because the configuration options changes for each. Now, accessing all the recurring dates for one model is quite easy:

>> er = EventRecurrence.new(:start_date => Date.today, :every => :month, :end_date => 6.months.from_now)
>> er.dates
=> [Thu, 15 Apr 2010, Sat, 15 May 2010, Tue, 15 Jun 2010,
Thu, 15 Jul 2010, Sun, 15 Aug 2010, Wed, 15 Sep 2010, Fri, 15 Oct 2010]

Since EventRecurrence is a model, these options are saved in database and we can update or use them for querying freely. For instance, if we want to look for all dates in a given period, we just search for all EventRecurrences that are in the range and collect the dates returned by recurrence. Here you can see a raw implementation of this idea:

class EventRecurrence < ActiveRecord::Base
  # Retrieves a list of all dates for a period
  def self.dates_between(start_date, end_date)
    # Filtering EventRecurrence on the period using a between named scope
    recurrences = EventRecurrence.between(start_date, end_date)
 
    recurrences.inject([]) do |dates, recurrence|
      # Use the given dates instead of the ones in the DB
      dates.concat(recurrence.dates(:starts => start_date, :until => end_date))
    end
  end
end

This is just an initial post showing some ideas to get you going with recurring events. If you are interested, there is a lot of information related to this topic, like Recurring Event in Calendars, an article by Martin Fowler, and the iCal RFC2445 which includes calendar specifications.

And you, have some different solutions about recurring events to share with us?