Category Archives: JavaScript

by Sam Gao

Don’t Feed the Trolls!

I gave my first-ever keynote this week at Fluent Conference. It was fun and terrifying, in particular because I spoke about a non-technical topic, trolling in the web community. Here is the video:

UPDATE: If you would like to take the test I mentioned to uncover your own biases, it is a research project called Project Implicit from Harvard University. Please forgive the 1999 styling of the site. :)

And, Don’t feed the trolls slides.

Photo Credit: Sam Gao

Welcoming Nicholas Zakas to the Team

I am so very pleased to announce that Nicholas Zakas and I are joining forces to form a consulting duo. Nicholas has spent the last five years defining what it meant to to be a client-side engineer at Yahoo!. He consistently raised the client-side glass ceiling with his commitment to good code and practical solutions. He also literally wrote the book on JavaScript Performance. Like me, Nicholas cares deeply about performance and scalability. And, most importantly, we share a love of finding elegant solutions to hard problems, which we feel makes us a good match.

I’ll let Nicholas speak for himself:

I’ll be … teaming up with my friend (and former Yahoo) Nicole Sullivan to do consulting work. Nicole and I have talked off and on about working together on outside projects after having fun working together on a couple of projects at Yahoo!. Between the two of us, we hope to provide a wide range of front-end consulting services including performance evaluations, general architecture, and of course, JavaScript and CSS. If you’re interested in hiring us, please email projects (at) stubbornella.org.
Nicholas Zakas

Please come see us at Velocity Conference on June 14.

Reflows & Repaints: CSS Performance making your JavaScript slow?

I’ve been tweeting and posting to delicious about reflows and repaints, but hadn’t mentioned either in a talk or blog post yet.

I first started thinking about reflows and repaints after a firey exchange with Mr. Glazman at ParisWeb. I may be stubborn, but I did actually listen to his arguments. :) Stoyan and I began discussing ways to quantify the problem.

Going forward the performance community needs to partner more with browser vendors in addition to our more typical black box experiments. Browser makers know what is costly or irrelevant in terms of performance. Opera lists repaint and reflow as one of the three main contributors to sluggish JavaScript, so it definitely seems worth a look.

Let’s start with a little background information. A repaint occurs when changes are made to an elements skin that changes visibility, but do not affect its layout. Examples of this include outline, visibility, or background color. According to Opera, repaint is expensive because the browser must verify the visibility of all other nodes in the DOM tree. A reflow is even more critical to performance because it involves changes that affect the layout of a portion of the page (or the whole page). Reflow of an element causes the subsequent reflow of all child and ancestor elements as well as any elements following it in the DOM.

For example:

<body>
<div class=”error”>
	<h4>My Module</h4>
	<p><strong>Error:</strong>Description of the error…</p>
	<h5>Corrective action required:</h5>
	<ol>
		<li>Step one</li>
		<li>Step two</li>
	</ol>
</div>
</body>

In the html snippet above, a reflow on the paragraph would trigger a reflow of the strong because it is a child node. It would also cause a reflow of the ancestors (div.error and body – depending on the browser). In addition, the h5 and ol would be reflowed simply because they follow that element in the DOM. According to Opera, most reflows essentially cause the page to be re-rendered:

Reflows are very expensive in terms of performance, and is one of the main causes of slow DOM scripts, especially on devices with low processing power, such as phones. In many cases, they are equivalent to laying out the entire page again.

So, if they’re so awful for performance, what causes a reflow?

Unfortunately, lots of things. Among them some which are particularly relevant when writing CSS:

  • Resizing the window
  • Changing the font
  • Adding or removing a stylesheet
  • Content changes, such as a user typing text in
    an input box
  • Activation of CSS pseudo classes such as :hover (in IE the activation of the pseudo class of a sibling)
  • Manipulating the class attribute
  • A script manipulating the DOM
  • Calculating offsetWidth and offsetHeight
  • Setting a property of the style attribute

Mozilla article about reflows that outlines causes and when they could be reduced.

How to avoid reflows or at least minimize their impact on performance?

Note: I’m limiting myself to discussing the CSS impact of reflows, if you are a JavaScripter I’d definitely recommend reading my reflow links, there is some really good stuff there that isn’t directly related to CSS.

  1. Change classes on the element you wish to style (as low in the dom tree as possible)
  2. Avoid setting multiple inline styles
  3. Apply animations to elements that are position fixed or absolute
  4. Trade smoothness for speed
  5. Avoid tables for layout
  6. Avoid JavaScript expressions in the CSS (IE only)

Change classes as low in the dom tree as possible

Reflows can be top-down or bottom-up as reflow information is passed to surrounding nodes. Reflows are unavoidable, but you can reduce their impact. Change classes as low in the dom tree as possible and thus limit the scope of the reflow to as few nodes as possible. For example, you should avoid changing a class on wrapper elements to affect the display of child nodes. Object oriented css always attempts to attach classes to the object (DOM node or nodes) they affect, but in this case it has the added performance benefit of minimizing the impact of reflows.

Avoid setting multiple inline styles

We all know interacting with the DOM is slow. We try to group changes in an invisible DOM tree fragment and then cause only one reflow when the entire change is applied to the DOM. Similarly, setting styles via the style attribute cause reflows. Avoid setting multiple inline styles which would each cause a reflow, the styles should be combined in an external class which would cause only one reflow when the class attribute of the element is manipulated.

Apply animations with position fixed or absolute

Apply animations to elements that are position fixed or absolute. They don’t affect other elements layout, so they will only cause a repaint rather than a full reflow. This is much less costly.

Trade smoothness for speed

Opera also advises that we trade smoothness for speed. What they mean by this is that you may want to move an animation 1 pixel at a time, but if the animation and subsequent reflows use 100% of the CPU the animation will seem jumpy as the browser struggles to update the flow. Moving the animated element by 3 pixels at a time may seem slightly less smooth on very fast machines, but it won’t cause CPU thrashing on slower machines and mobile devices.

Avoid tables for layout (or set table-layout fixed)

Avoid tables for layout. As if you needed another reason to avoid them, tables often require multiple passes before the layout is completely established because they are one of the rare cases where elements can affect the display of other elements that came before them on the DOM. Imagine a cell at the end of the table with very wide content that causes the column to be completely resized. This is why tables are not rendered progressively in all browsers (thanks to Bill Scott for this tip) and yet another reason why they are a bad idea for layout. According to Mozilla, even minor changes will cause reflows of all other nodes in the table.

Jenny Donnelly, the owner of the YUI data table widget, recommends using a fixed layout for data tables to allow a more efficient layout algorithm. Any value for table-layout other than "auto" will trigger a fixed layout and allow the table to render row by row according to the CSS 2.1 specification. Quirksmode shows that browser support for the table-layout property is good across all major browsers.

In this manner, the user agent can begin to lay out the table once the entire first row has been received. Cells in subsequent rows do not affect column widths. Any cell that has content that overflows uses the ‘overflow’ property to determine whether to clip the overflow content.

Fixed layout, CSS 2.1 Specification

This algorithm may be inefficient since it requires the user agent to have access to all the content in the table before determining the final layout and may demand more than one pass.

Automatic layout, CSS 2.1 Specification

Avoid JavaScript expressions in the CSS

This rule is an oldie but goodie. The main reason these expressions are so costly is because they are recalculated each time the document, or part of the document, reflows. As we have seen from all the many things that trigger a reflow, it can occur thousands and thousands of times per second. Beware!

Further study

The Yahoo! Exceptional Performance team ran an experiment to determine the optimal method to include an external stylesheet. We recommended putting a link tag in the head because, while it was one second slower (6.3 to 7.3 seconds) all the other methods blocked progressive rendering. While progressive rendering is non-negotiable (users hate staring at a blank screen), it does make me curious about the effects of rendering, repaints, reflows and resulting CPU thrashing on component download and overall response time. If we could reduce the number of reflows during loading could we maybe gain back a tenth of the lost time (100ms)? What if it was as much as half?

At SXSW I was trying to convince Steve that reflows are important by telling him about an experiment I’ve been meaning to run for a long time, but just haven’t had time. I do hope someone can pick up where I left off (hint! hint!). While loading the page I’d like to intentionally trigger reflows at various rates. This could perhaps be accomplished by toggling a class name on the body (experiment) versus the last child of the body with no descendants (control). By comparing the two, and increasing in the number of reflows per second, we could correlate reflows to response time. Measuring the impact of reflows on JS responsiveness will be harder because anything we do to trigger the reflows will likely impact the experiment.

In the end, quantifying the impact is only mildly interesting, because browser vendors are telling us it matters. Perhaps more interesting is to focus on what causes reflows and how to avoid them. That will require better tools, so I challenge browser vendors and the performance community to work together to make it a reality!

See it in action

Perhaps you are a visual person? These videos are a really cool visualization of the reflow process.

  1. http://www.youtube.com/watch?v=nJtBUHyNBxs
  2. http://www.youtube.com/watch?v=ZTnIxIA5KGw
  3. http://www.youtube.com/watch?v=dndeRnzkJDU

Reflow gone amok

In order to improve performance browser vendors may try to limit reflows from affecting adjacent nodes or combine several reflows into one larger change such as Mozilla’s dirty reflows. This can improve performance, but sometimes it can also cause display problems. You can use what we’ve learned about reflows and trigger them when necessary to correct related display problems.

For example, when toggling between tabs on our image optimization site, http://smush.it, the height of the content is variable from tab to tab. Occasionally the shadow gets left behind as it is several ancestor nodes above the content being toggled and its container may not be reflowed. This image is simulated because the bug is difficult to catch on camera as any attempts to shoot it cause the reflow that corrects it. If you find yourself with a similar bug, move the background images to DOM elements below the content being toggled.

Smush.it! with un-reflowed shadows

Smush it on tab change in Firefox only.

Another example is dynamically adding items to an ordered list. As you increase from 9 to 10 items or 99 to 100 items the numbers in the list will no longer line up properly across all navigators. When the total number increases by an order of magnitude and the browser doesn’t reflow siblings, the alignment is broken. Quickly toggling the display of the entire list or adding a class, even if it has no associated styles, will cause a reflow and correct the alignment.

Tools

A few tools have made waves lately. Stoyan Stefanov and I have been looking for decent ways to measure reflows and repaints and there are a few tools which show promise (despite being very early alpha). Beware, some of these seriously destroyed my browser before I got them working correctly. In most cases you’ll need to have installed the latest nightly builds.

When Mozilla announced the MozAfterPaint Firefox API, the internets were abuzz.

Has anyone else seen any cool tools for evaluating reflows? Please send them my way!

And a couple other tools not directly dealing with reflows.

Ultimately, we need a cross browser tool to quantify and reduce reflows and repaints. I’m hoping that the performance community can partner with browser vendors to make this tool a reality. The browser vendors have been telling us for a while that this was where we needed to look next, the ball is in our court.

Object Oriented CSS, Grids on Github

How do you scale CSS for millions of visitors or thousands of pages? Object Oriented CSS allows you to write fast, maintainable, standards-based front end code. It adds much needed predictability to CSS so that even beginners can participate in writing beautiful websites.

I recently presented Object Oriented CSS for high performance web applications and sites at Web Directions North 2009. If you didn’t attend my talk, you are probably asking yourself “what in the world is OO-CSS?”

Object Oriented CSS: Two main principles

1. Separate structure and skin
2. Separate container and content

I’m writing a framework to demonstrate the technique, but more than anything, Object Oriented CSS is a different way of approaching CSS and the cascade. It draws on traditional software engineering concepts like extending objects, modularity, and predictability. Solutions are judged based on their complexity, in other words, “what happens to the size of the CSS file as more pages and modules are added?”

The answer, for most sites, is that it grows out of control and becomes an unmaintainable tangle of spaghetti code. People often complain about CSS, and rightly so — even though it inspired a rant, I understand their frustration.

Current methods for writing CSS require expert level ability just to get started. To become a CSS expert, you need to spend couple years coding away in your basement by yourself before you are remotely useful. Front-end engineering needs to accomodate entry level, mid level, and architect level developers, but our sites are too brittle. You may have a perfectly accessible or high performance website, and then the first newbie to touch it, ruins it. Our code should be robust enough that newbies can contribute while maintaining the standards we’ve set.

We don’t trust each others code

Imagine a JavaScript developer wrote a function to return area, and every now and then it randomly returned the diameter instead. The function would never make it through a code review, and yet we tolerate the same thing from CSS, as if it were immune from normal programming best-practices. This is why CSS code reuse is almost nonexistent. An object should behave predictably no matter where you place it on the page, which is why Object Oriented CSS avoids location dependent styles.

What not to do

#myModule h2{...}
#myModule span{...}
#myModule #saleModule{...}
#myOtherModule h3{...}
#myOtherModule span{...}

Developers have tried to sandbox their CSS into individual modules, to protect against the cascade. But in doing so we’ve ended up with a mess.

Object Oriented CSS Grids on github

My Object Oriented CSS grids and templates are open sourced on github. They have all the functionality of YUI grids plus some important features.

  • Only 4kb, half the size of YUI grids. (I was totally happy when I checked the final size!)
  • They allow infinite nesting and stacking.
  • The only change required to use any of the objects is to place it in the HTML, there are no changes to other places in the DOM and no location dependent styling. Eases back-end development and makes it a lot easier to manage for newbies.
  • Solution for sub-pixel rounding errors.

http://wiki.github.com/stubbornella/oocss

Check out template.css and grids.css and the docs on the github wiki.

My prediction is that you’ll be writing complex layouts in less than 24 hours without adding a line to the CSS file.

What’s up next?

Template and grids are ready for rock and roll. Please be my alpha testers, put them through their paces. Let me know if you find bugs or want additional functionality. I’m also hoping to contribute some of this back to YUI since they now have a github repository. How cool is that?

Rounded Corner Boxes and Tabs

Next up, modules. There are a million cool ways to create rounded corner boxes. I’m going to take several of my favorites (like CSS Mojo and Arnaud Gueras blocks) and convert them to OO-CSS. This will make it super easy for newbies to create their own modules, without needing to understand the minutiae of browser differences.

Video / Podcasts

YDN will publish a video of my talk and Web Directions North is putting out podcasts. I’ll tweet and post when that happens. The audio contains a lot more detail than the slides, so check it out as they become available.

Optimisation des Images : Les 7 erreurs à éviter at ParisWeb

Je vais parler (en francais! eek!) avec Eric Daspet de la performance des images pour le web a ParisWeb. Les inscriptions pour Paris Web 2008 sont officiellement ouvertes. Jusqu’au 15 octobre au soir, vous bénéficierez de tarifs réduits. Le conference sera lieu a Paris le 13-15 Novembre. J’attend vous voir bientot alors. ;)

Voila le proposition

Voulez-vous améliorer la vitesse de vos pages web et réduire l’impact écologique et monétaire de votre hébergement ? Voulez-vous faire ceci avec peu de changement de code et en gardant une belle interface graphique ? Cette session va vous apprendre les 7 étapes pour mettre votre site web au régime. Comment perdre des poids que votre site a pris en rajoutant les dernières nouveautés. Et, encore plus important, comment ne pas reprendre ce poids !

Quand on commence un site de zéro, il est forcement très rapide. Au fur et à mesure, en rajoutant des modules, des flux, des images, l’expérience de l’utilisateur devient plus riche, mais aussi plus frustrante quand l’internaute est forcé d’attendre trop longtemps pour le chargement de la page. De premier abord, l’optimisation des images semble basique, facile. Néanmoins, la plupart des sites les plus réputés au monde ne suivent pas encore tous les standards pour l’optimisation des images. Faites-vous les mêmes erreurs ?

L’audience va apprendre comment :

  1. Améliorer la vitesse des pages web
  2. Optimiser les poids des images
  3. Eviter les pièges les plus problématiques et implémenter les petits astuces pour rendre les sites plus performant. Utilisez-vous encore alphaImageLoader ? Quel type de dégradé est le moins performant ?
  4. Arranger vos sprites pour iPhone. Comment contourner ses limites de cache ?