The most efficient CSS reset pattern

I've recently been investigating web page performance and focusing on CSS efficiency to see where performance gains can be made. After using the Chrome CSS profiler, I came to the conclusion that my "reset" CSS file was taking a long time to parse and match selectors, slowing down the browser paint process.

Reset CSS files are used to normalise default DOM element styles, so that your custom styles will work effortlessly across all browsers.

Naturally then, the reset CSS must target many elements in order to change their style. However, how can this be done in the most efficient manner?

This useful website, CSSReset.com provides 5 popular reset methods for you to use.

For my experiment I have used each of the provided codes and implemented them in turn into my web page. I then run though a "script" of accessing certain parts of the website while the Chrome CSS profiler is running and measure the results of each. I have performed the script multiple times with each code snippet to ensure a valid result.

In short, my findings are: normalize.css has the best efficiency, by quite a long way, with YUI coming in second place.

The reason normalize.css is highly more efficient is that unlike the other scripts, it does not select all DOM elements in a single comma separated declaration, but breaks up the declarations into smaller segments.

Due to my project not using many DOM elements, the browser can skip parsing for many of these declarations making overall performance better.

This is interesting as normalize.css is the least used code snippet on the website, at the current time of writing.

I'd be interested to follow up on this and here any arguments for or against using a reset CSS in this manner.

Improve page performance with optimal CSS

There are certain CSS best practices that should be followed in order to increase CSS performance in the browser. These will help the browser to perform less DOM parsing and reduce the time of repaint events.

1. Browser reflow and repaint

If you are unfamiliar with the concepts of reflow and repaint, here are some articles that will get you up to speed:

2. Remove unused styles

Simply having styles that aren't used causes the browser to search the DOM for matches needlessly. This is wasted processor time. Additionally, the CSS file will have a higher page weight that is needlessly sent over the wire to the client.

It may not seem to make a huge difference but removing dead CSS code will greatly increase performance and additionally improve the project stability and maintainability.

Fix frozen OSX gestures without restart

Occasionally when working with OSX the magic mouse/trackpad gestures will stop working at random. This appears to be caused by 3rd party software interfering with the Dock, so restarting it will usually fix this problem rather than performing a computer restart.

You can restart the Dock program by opening a terminal window and issuing the following command:

killall Dock

Check size of localStorage usage in Chrome

localStorage is a great tool for JavaScript developers to persist information across multiple sessions. Due to its simple API, large browser support and and higher reliability than cookies, it can easily lead to the situation of overusing localStorage.

Since localStorage has a maximum size of 5MB the following snippet will help inspect what localStorage keys are being used and how much size is being allocated to each.

To give credit, I have taken the method here and added a total counter.

var total = 0;
for(var x in localStorage) {
  var amount = (localStorage[x].length * 2) / 1024 / 1024;
  total += amount;
  console.log( x + " = " + amount.toFixed(2) + " MB");
}
console.log( "Total: " + total.toFixed(2) + " MB");

Simply run this in the Chrome console or create a bookmarklet from the following code (Right click bookmark bar > Add Page > Copy the code as "URL")

javascript:var total = 0;for(var x in localStorage) {  var amount = (localStorage[x].length * 2) / 1024 / 1024;  total += amount;  console.log( x + "=" + amount.toFixed(2) + " MB");}console.log( "Total: " + total.toFixed(2) + " MB");

Which will give a similar output:

Matches = 0.40 MB
Matches_timestamp = 0.00 MB
Teams = 0.19 MB
Teams_timestamp = 0.00 MB
Total: 0.59 MB

OSX Convert image formats in terminal (GIF to PNG)

Answer found from Superuser: http://superuser.com/questions/571003/how-to-convert-gif-files-to-png-or-jpeg-in-os-x-with-command-line

Using the sips command, almost any image format can be converted into another, like so:

cd /directory/with/gif/images/
mkdir pngs
sips -s format png ./*.gif --out pngs

This will create new images with a png extension in the pngs subfolder to match the gif version.

Dynamically append LESS.js stylesheets

Here is a function that can be called to dynamically apply a LESS.js stylesheet to the DOM after the page has finished loading. The following code snippet uses jQuery for convenience.

 function loadLESS ( filename ) {
    // If LESS isn't available, do nothing
    if ( !window.less ) { return;}

    // Create LESS link and add to <head>
    var $link = $("<link type='text/css' rel='stylesheet/less' />");
    $link.attr("href", filename + ".less");
    $("head").append( $link );

    // Notify LESS that there is a new stylesheet
    less.sheets.push( $link[0] );
    less.refresh();
}

The important parts are after applying the new link tag to the head section, the raw DOM node $link[0] must be added to the less.sheets array and then refresh called to apply the changes to the web page.

Also remember that the rel attribute for the link tag must be set to "stylesheet/less" rather than just "stylesheet".

How to handle user time zones in Ruby on Rails

Displaying a date time correctly for users around the world is made very easy with Ruby on Rails. The time zone can be set per request and loaded from the logged in user's configuration. All of the default time zones are already built into Ruby on Rails and provides the ability to add custom ones, for custom cities too.

Model

First we need to allow the user to choose their desired timezone, so a migration is required:

class AddTimezoneToUser < ActiveRecord::Migration
  def change
    add_column :users, :timezone, :string
  end
end

Then of course this change needs to be applied to the database.

$ rake db:migrate

Then ensure the User model has timezone under its accessible attributes

class User < ActiveRecord::Base
    attr_accessible :email, :name, :timezone, :created_at, :updated_at
end

View

Next we must provide a field to choose from. In this example I am simply adding a new form field to my users/_form.html.erb partial. Here we use the built in time_zone_select form helper.


Which will automatically give a result similar to the following screenshot. The select menu is prefilled from the Rails ActiveSupport::TimeZone class.

image

Controller

Lastly, an application controller before_filter is required that will set the time zone for each request.

class ApplicationController < ActionController::Base
  protect_from_forgery
  before_filter :set_timezone

  private

  def set_timezone
    tz = current_user ? current_user.timezone : nil
    Time.zone = tz || ActiveSupport::TimeZone["London"]
  end
end

Here current_user points to the logged in user record. This is the default behavior when using the "devise" gem. If the current user does not have a timezone, I choose to fallback to GMT (London) time. This can be changed for whatever default makes sense in your given project.

Append an HTML string to the DOM without a JavaScript Library

In the event where appending new nodes to the DOM via JavaScript is required but there is no access to a library such as jQuery or Prototype.JS, this handy snippet allows an easy librabry-like API with a tiny amount of code:

 function append ( elString, parent ) {
    var div = document.createElement( "div" );
    div.innerHTML = elString;
    document.querySelector( parent || "body" ).appendChild( div.firstChild );
 }

This snippet can be used easily:

// Append a link tag to the head
append( "<link rel='stylesheet' href='css/foo.css' />", "head" );

// Append a parapgraph to the body
append( "<p>My text</p>" );

// Append a new list item
append( "<li>Cheese</li>", "ul.shopping-list" );

Install Node.JS on Debian Wheezy

Official Method

The official Node.JS install guide recommends manually downloading and building the Node.JS package for Debian. This can be done using the following set of commands:

sudo apt-get install python g++ make checkinstall
mkdir ~/node_js_src && cd $_
wget -N http://nodejs.org/dist/node-latest.tar.gz
tar xzvf node-latest.tar.gz && cd node-v*
./configure
checkinstall
sudo dpkg -i node_*

This install method should work fine but will take a long time to complete on the Raspberry Pi's hardware. For this reason I experimented a little and found a quicker install method that doesn't require a manual compile, by using the Ubuntu package.

Ubuntu Method

This install method will be much faster than the official method but is not designed for Debian Wheezy, so use at your own risk! Personally I have not had any trouble with my node install yet but I cannot guarantee this will be the case for anyone else.

sudo apt-get update
sudo apt-get install -y python-software-properties python g++ make
sudo add-apt-repository ppa:chris-lea/node.js

At this point the file with the new repository details must be edited. Open the file: /etc/apt/sources.list.d/chris-lea-node_js-wheezy.list with a text editor like vim and change the word "wheezy" to "lucid". Thanks to Ken Yap for this hint.

Now, go on and finish installing Node.

sudo apt-get update
sudo apt-get install -y nodejs

Install LAMP server on Debian Wheezy from scratch

Debian Wheezy is the recommended UNIX package for a Raspberry Pi. After setting up your device and completing the raspi-config steps, simply run the following commands line-by-line in the bash terminal to create a functioning web server.

sudo apt-get install -y build-essential make
sudo apt-get install -y mysql-server mysql-client
sudo apt-get install -y apache2
sudo apt-get install -y php5 libapache2-mod-php5

The web server root can be found at /var/www/ and will contain a default index.html file. Type the IP address of the Raspberry Pi into a web browser and a page similar to this should be presented.

Apache default index

The root web directory is owned by the Apache user so to make changes within it write and execute rights must be given to the current user. Please note that this may compromise security, so not advised for a publicly accessible server.

sudo chmod a+wx /var/www/

Now files can be created and saved in the www directory. Create a new file called info.php and type the following into it:

 <?php phpinfo(); ?>

Again, open the Raspberry Pi IP address in a web browser but this time add /info.php to the URL. If everything has been installed correctly an information screen of the PHP environment will be displayed.

PHP Info Screen

To install Node.JS on Debian Wheezy, please see this article: Install Node.JS on Debian Wheezy

© Blake Simpson, 2012 – 2018