Home

Awesome

css perf

This project is archived and will not be maintained or updated.

css-perf is a completely unscientific way of testing CSS performance. Most of these tests will revolve around methodologies and techniques for determining effective CSS architecture. Put another way, I want to know what works best given a particular comparison of CSS strategies.

Table of contents

How "testing" is done

Yes, it's in quotes for a reason. None of this is super accurate, but it's all very interesting to me. I merely use page loads at this point to gauge overall time spend on a particular page by Safari and Chrome.

More specifically:

Things worth noting about this process:

Additional context and background information is provided in the test results sections below.

Original test results

Explanation and analysis between sample pages featuring high number of elements.


Attribute vs class selectors

This tests the rendering performance of the same page of 5,000 elements with the same class. An attribute selector looks something like [class^="column-"] { ... }. A class selector looks like .column-class { ... }. At first glance, the class selector page renders 43ms faster (a 9.3% improvement) in Safari 7.0.1.

PageSafari 7.0.1Chrome 33
Attribute selectors485ms260.17ms
Class selectors442ms244.37ms

The time spent recalculating styles is neglible I think, but the difference here is interesting. Consider the following context for this test:

In other words, this super edge case comparison of a large number of the same elements isn't that accurate. I'd wager most sites would see a larger disparity when sticking to classes only, as opposed to wide use of attribute selectors.

Conclusion? Based on this test, my personal experience with Twitter, Bootstrap, and GitHub, and the feedback of others, I'd stick to classes for widely used components.


Box-sizing resets

This tests the rendering performance of the (relatively new) standard box-sizing: border-box; reset. Popularized by Paul Irish with his * { Box-sizing: Border-box } FTW post, it looks like this:

*,
*:before,
*:after {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}

I've had a hunch that this is slower for one reason or another than say splitting up the selectors like so:

* {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}
*:before,
*:after {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}

And as it turns out, it is slower in the first run. Splitting the selector up saves 8.2ms (a 16% improvement) in page render time as reported by a single load in Safari 7.0.1.

PageSafari 7.0.1Chrome 33
Standard box-sizing reset55.5ms108.61ms
Split box-sizing reset47.3ms98.87ms

The problem with this test is that the page rendering time is super inconsistent. The first test numbers are above. Subsequent refreshes yield wildly different numbers in both Safari 7.0.1 and Chrome 33. Sometimes the render time is doubled or the improvement reversed between the two options.

Conclusion? I have no idea.


Grid techniques

This test compares three CSS grid techniques: floats, display: inline-block;, and display: table-cell;. The test page has a few hundred columns in standard layouts, so it's a super basic set of pages. The only differences are in the actual grid CSS.

PageSafari 7.0.1Chrome 33
Floats246ms424.94ms
Inline-block306ms439.19ms
Flexbox252ms262.41ms
Tables271ms265.53ms

Some background and context:

Conclusion? Floats have been CSS stable for many years, and I see no reason to move away. That said, I have no idea why the numbers are so crazy different between Safari and Chrome—especially for floats and inline-block.


Background vs background-color

Comparison of 18 color swatches rendered 100 times on a page as small rectangles, once with background and once with background-color.

PageSafari 7.0.1Chrome 33
background44.9ms34.45ms
background-color87.5ms69.34ms

While these numbers are from a single page reload, with subsequent refreshes the render times changed, but the percent difference was basically the same every time.

That's a savings of almost 42.6ms, almost twice as fast, when using background instead of background-color in Safari 7.0.1. Chrome 33 appears to be about the same.

This honestly blew me away because for the longest time for two reasons:

Conclusion? Stick to background, I guess. Ugh.


Average test results

This is a second set of test results, averaging 10 page load times in Safari 7.0.1 and Chrome 33. Cache was always disabled in both browsers with Inspector open. All times are in milliseconds.

Safari 7.0.1

backgroundbackground-colorbox-sizingbox-sizing splitattr selectorsclass selectorsgrid - floatsgrid - inline-blockgrid - tablegrid - flexbox
34.835.748.356.310392.7155174129129
35.440.745.554.1113103171190131130
34.437.248.147.511489.4167177148122
35.874.851.848.910389.1208184141121
51.639.746.564.3106100165183147125
37.63642.545.8118104168181128121
33.444.988.868.9113103179214141133
31.837.145.441.511588.3170185137125
31.83862.34511099.4164177143135
57.836.939.444.1116102151182145115
38.4442.151.8651.64111.197.09169.8184.7139125.6

Chrome 33

backgroundbackground-colorbox-sizingbox-sizing splitattr selectorsclass selectorsgrid - floatsgrid - inline-blockgrid - tablegrid - flexbox
54.7198.8115.84118.03296.68239.62399.82492.73297.2302.14
76.9760.43111.39102.29302.84249.69405.4444.31274.17267.38
54.4756.31100.9498.88274.51249.12409.19446.83273.26276.91
55.0656.01105.1104.13277.23243.7409.89451.68267.64274.92
56.1259.4797.72106.09289.38266.6404.1444.12275.73271.13
76.3756.68100.32100.2281.62254.81412.51446.36271.66266.55
59.5955.37103.25119.43269.07247.56406.63458.51279.44262.78
55.7759.18105.26102.27270.95244.96405.68473.82270.63266.63
77.6658.08103.28100.28268.88245.84408.32440.71270.76279.45
53.7359.2198.98105.21266.24255.96398.81469.13269.87271.98
62.04561.954104.208105.681279.74249.786406.035456.82275.036273.987

Differences between test results

The differences in times between these averages and the individual tests earlier is astonishing. Further testing—without me at the helm—is definitely needed. Here's what's different:

Bottom line, though? The disparity is not at huge as I saw earlier when averaged out, apparently.

Updated conclusions from averages

Let's revisit the conclusions I had earlier from single tests against the averages:

So, the averages match some of the earlier expectations. That last one is the most important since it blew up on Twitter. The difference is clearly not as stark when averaged out.

A note on CSS performance testing

These kind of tests are cheats and always going to be somewhat inaccurate from the real world. They involve duplicating series of the same elements over and over to stress test a page. That's useful, but that's not everything. In the future, a more accurate real world example page is needed.


Feedback

Tell me I'm wrong, that I'm an idiot, or that I'm missing a test case you'd like to see. Let me know with an issue, or open a pull request. Whatever it is, just go for it.

License

Released with <3 under MIT by Mark Otto.