The first step when creating selectors for optimal browser rendering is to determine how efficient your CSS selectors are.
A common mistake that people make is creating selectors that match a large number of elements on the page. This is an issue because the browser creates a document tree of all the elements being displayed on the page and matches these elements with any specified styles/classes according to three levels – cascading, inheritance, and ordering rules. When this is done, the CSS engine tries to match styles with elements based on the rules supplied in the CSS from the right-most selector (the “key”) until it finds a match or discards it and moves on. Therefore if there are multiple matches, it will only see the first one and disregard the rest.
Removing unused CSS is a BIG step in improving rendering performance in browsers. The more specific you are when defining your rules and avoiding repeating or redundant class/styles, the easier and faster it is for the style engine to find matches and continue forward.
Some examples of CSS rules that slow down the rendering process and are inefficient to use are:
- Descendant selectors that use a universal selector as the “key” (`body * { color: #999;}`). This is inefficient because, for each element that matches “body”, the browser must now evaluate every ancestor element in the DOM until it finds a match or reaches the root element. This means, the less specific the key, the greater number of elements that have to be evaluated.
- Using child/adjacent selectors with a universal key ( `body > * { color: #999;}`). Even though this approach is better than descendant selectors, it is still inefficient because the browser’s CSS engine still has to evaluate twice as many elements on the page, which is doubly more expensive in terms of rendering and evaluation.
- Redundancy in terms of adding tags or classes to an ID selector (ex – “`form#UserLogin { font-size: 11px;}`”). In this example, there is no practical reason to add a tag or class qualifier to the ID because it’s information that is evaluated for no apparent reason, which bogs down rendering time.
To avoid slower page loads and browser rendering, it is recommended that you avoid using universal key selectors, make your CSS rules as specific as possible, remove redundancy in your CSS, avoid descendant, child, or adjacent selectors as much as possible, and use class and ID selectors instead.
Another good practice is removing all of your inline styles and placing them in a corresponding style sheet or, if need be, in the head of the page itself. Also, when using external style sheets, it’s best to link to them instead of using “@import”.
The last two steps you can take to speed up browser rendering are:
- Specify the height and width of all images. If there are no dimensions, the browser will have to reflow the layout once the images are downloaded. However, never scale images by using smaller dimensions than what were specified originally when the image was created.
- Specify a character set that includes setting a content type and character encoding. This prevents the browsers from having to find the type on its own using algorithms, which of course causes additional delays and security risks. These are set in your HTTP header or HTML meta tag. It’s important that these “charsets” match the HTML authoring tool you are using to prevent mismatched encoding, which can lead to your page being rendered incorrectly and delays in redrawing the page in the browser.
Just following these additional steps can vastly improve the speed and rendering of your HTML documents in the browser, leading to a better, more efficient browser experience for your end user.