Top 10 CSS Performance Tips

Written by wownetort | Published 2022/11/14
Tech Story Tags: css | html | frontend | web | performance | optimization | tips | hackernoon-top-story | hackernoon-es | hackernoon-hi | hackernoon-zh | hackernoon-vi | hackernoon-fr | hackernoon-pt | hackernoon-ja

TLDRvia the TL;DR App

Hi everyone! There are a lot of tips and tricks about CSS styling. But not in this article. Today I want to talk about how to use CSS more efficiently and make your platform faster!

1. Simple selectors

CSS has a wide, flexible array of coding options you can use to target HTML elements for styling. Over the years, experts have advised developers to write simple selectors to reduce the load on the browser and keep the code clean and simple. Even the most complex CSS selectors take milliseconds to parse, but reducing complexity will reduce file sizes and aid browser parsing

Do NOT:

main > div.blog-section + article > * {
        /* Code here */
}

DO:

.hero-image {
        /* Code here */
}

2. Critical Inline CSS

You can inline critical CSS rules. This improves performance by:

  1. Identifying essential styles used by elements above the fold (those visible when the page loads)

  2. Inlining that critical CSS into a <style> tag in your <head>

  3. Loading the remaining CSS asynchronously to avoid render blocking. This can be accomplished by loading the stylesheet in a “print” style that the browser gives a lower priority. JavaScript then switches it to an “all” media style once the page has loaded.

<style>
/* critical styles */
body { font-family: sans-serif; color: #111; }
</style>
<!-- load remaining styles -->
<link rel="stylesheet" href="/css/main.css" media="print" onload="this.media='all'">
<noscript>
  <link rel="stylesheet" href="/css/main.css">
</noscript>

3. Avoid @import

The @import at-rule allows any CSS file to be included within another. This appears a reasonable way to load smaller components and fonts. But it is not.

@import rules can be nested so the browser must load and parse each file in series.

Multiple <link> tags within the HTML will load CSS files in parallel, which is considerably more efficient — especially when using HTTP/2.

Do NOT:

/* main.css */
@import url("style1.css");
@import url("style2.css");
@import url("style3.css");

DO:

<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="layout.css">
<link rel="stylesheet" href="carousel.css">

4. Preload CSS Files

The <link> tag provides an optional preload attribute that can start a download immediately rather than waiting for the real reference in the HTML.

<!-- preload styles -->
<link rel="preload" href="/css/main.css" as="style" />
<!-- some code -->
<!-- load preloaded styles -->
<link rel="stylesheet" href="/css/main.css" />

5. Progressive Rendering

Rather than using a single site-wide CSS file, progressive rendering is a technique that defines individual stylesheets for separate components. Each is loaded immediately before a component is referenced in the HTML.

Each <link> still blocks rendering, but for a shorter time, because the file is smaller. The page is usable sooner, because each component renders in sequence; the top of the page can be viewed while remaining content loads.

<head>
  <!-- core styles used across components -->
  <link rel='stylesheet' href='base.css' />
</head>
<body>
  <!-- header component -->
  <link rel='stylesheet' href='header.css' />
  <header>...</header>

  <!-- primary content -->
  <link rel='stylesheet' href='content.css' />

  <main>
    <!-- form styling -->
    <link rel='stylesheet' href='form.css' />
    <form>...</form>
  </main>

  <!-- header component -->
  <link rel='stylesheet' href='footer.css' />
  <footer>...</footer>
</body>

6. Use Media Query Rendering

A single concatenated and minified will benefit most sites, but sites that require a significant quantity of larger screen styles could split CSS files and load using a media query.

<!-- core styles loaded on all devices -->
<link rel="stylesheet" href="core.css">
<!-- served to screens at least 40em wide -->
<link rel="stylesheet" media="(min-width: 40em)" href="40em.css">
<!-- served to screens at least 80em wide -->
<link rel="stylesheet" media="(min-width: 80em)" href="80em.css">

7. Adopt SVG Images

Scalable vector graphics (SVGs) are typically used for logos, charts, icons, and simpler diagrams. Rather than define the color of each pixel like JPG and PNG bitmaps, an SVG defines shapes such as lines, rectangles and circles in XML.

Simpler SVGs are smaller than equivalent bitmaps and can infinitely scale without losing definition. An SVG can be inlined directly in CSS code as a background image. This can be ideal for smaller, reusable icons and avoids additional HTTP requests.

SVG example:

<svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 800 600">
  <circle cx="400" cy="300" r="50" stroke-width="5" stroke="#f00" fill="#ff0" />
<svg>

SVG usage example:

.mysvgbackground {
  background: url('data:image/svg+xml;utf8,<svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 800 600"><circle cx="400" cy="300" r="50" stroke-width="5" stroke="#f00" fill="#ff0" /></svg>') center center no-repeat;
}

8. Style SVGs with CSS

SVGs can be embedded directly within an HTML document. This adds the SVG nodes directly into the DOM. Therefore, all SVG styling attributes can be applied using CSS.

SVG in DOM:

<body>
  <svg class="mysvg" xmlns="https://www.w3.org/2000/svg" viewBox="0 0 800 600">
    <circle cx="400" cy="300" r="50" />
  <svg>
</body>

SVG styles:

circle {
  stroke-width: 1em;
}

.mysvg {
  stroke-width: 5px;
  stroke: #f00;
  fill: #ff0;
}

The volume of embedded SVG code is reduced and the CSS styles can be reused or animated as necessary.

Note that using an SVG within an <img> tag or as a CSS background image means they’re separated from the DOM, and CSS styling will have no effect.

9. Avoid Base64 Encoding

You can encode images to base64 strings, which you can use as data URIs in HTML <img> tags and CSS backgrounds.

This reduces the number of HTTP requests, but it harms CSS performance:

  • base64 strings can be 30% larger than their binary equivalent.
  • browsers must decode the string before an image can be used, and
  • altering one image pixel invalidates the whole CSS file.

Only consider base64 encoding if you’re using very small, infrequently changing images where the resulting string is not significantly longer than a URL.

Do NOT:

.background {
  background-image: url('data:image/jpg;base64,ABC123...');
}

DO:

.svgbackground {
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600"><circle cx="300" cy="300" r="150" stroke-width="3" stroke="#f00" fill="#ff0" /></svg>');
}

10. Short tips

  1. Replace Images with CSS Effects - defining an “image” using CSS code uses considerably less bandwidth and is easier to modify or animate later.

  2. Use Modern Layout Techniques - Flexbox and Grid.

  3. Use CSS Animations - transitions and animations will always be faster than JavaScript.

  4. Avoid Expensive Properties - some CSS requires more processing than others.

    1. border-radius
    2. box-shadow
    3. text-shadow
    4. opacity
    5. transform
    6. filter
    7. position: fixed
    8. backdrop-filter
    9. background-blend-mode

P.S. Thanks for reading!

More articles about frontend development:

  1. Top 9 Tips to Improve React Performance
  2. Some HTML, CSS Little Secrets In One Article
  3. Top Lesser Known HTML 5 & CSS 3 Tips and Best Practices
  4. Top 12 Lesser Known Tips for JavaScript Best Practices


Written by wownetort | 8+ years full-stack developer
Published by HackerNoon on 2022/11/14