Performance

15 web performance peculiarities

A set of performance tips that are unconventional, controversial, counter-intuitive, or reverse previous advice.

9 minute read Performance Craig Buckler

At the end of 2026, httparchive.org reports that the median web page is 2,900KB, makes 70 requests, loads 740KB of JavaScript, and takes up to six seconds to appear on a fast connection. Half the web is worse.

It need not be that way, but web performance can be challenging. Seemingly good advice can change as browsers evolve and techniques progress. Watch out for the following problems on your site, but be aware some nuance is necessary for all your decisions!

1. Not all assets are equal

1MB of images, audio, or video is significant but browser parsing is less onerous than a similar amount of HTML, CSS, or JavaScript. In particular, JavaScript takes significantly more time to download, parse, and execute.

2. Use image width and height attributes

In the early years of the web, developers conscientiously added width and height attributes to every <img> because it reserved space during the page download and avoided reflows.

<img src="myimage.png" width="400" height="300" alt="my image">

Developers then removed those attributes when Responsive Web Design techniques arrived in 2010. When used, some browsers failed to size images to their CSS containers:

img {
  width: 100%;
  height: auto;
}

This is no longer the case. You should use width and height because it allows browsers to calculate the image's aspect ratio and reserve layout space. Alternatively, you can set the CSS aspect-ratio property:

img.myimage {
  aspect-ratio: 400 / 300;
}

width and height attributes are especially important when you use lazy loading...

3. Lazy-loading affects LCP

Images can be lazy loaded so they're downloaded by the browser shortly before they scroll into view:

<img src="myimage.png" loading="lazy" width="400" height="300" alt="my image">

It seems reasonable to apply this to every image, but it affects the Largest Contentful Paint (LCP) metric shown in tools such as DevTools Lighthouse and PageSpeed Insights.

LCP reports the render time of the largest image, text block, or video visible in the viewport. While the first image should be visible and loaded immediately, loading="lazy" adds a short delay. Either remove it or use loading="eager" on your primary image.

4. Concatenated files can make pages slower

Historically, developers concatenated (built, joined, bundled) CSS and JavaScript into single files to reduce the number of HTTP requests. Similarly, image sprites positioned multiple images in a single file. This worked well when browsers had a limited number of HTTP/1.1 connections.

Most hosts now offer HTTP/2 or HTTP/3 which use multiplexed connections. Many responses share a single connection so multiple requests are less expensive.

You should also consider splitting and caching. Assume you've created a complex web application with 1,000KB of JavaScript split over ten 100KB files. Not every part of the application requires all ten files so you can load them on demand to improve performance. Updating one file then results in a 100KB update for those users who've already loaded the application. With a single bundled file, a single character change requires the user to re-download, parse, and execute the full 1MB.

That said, bundling can tree-shake unnecessary code and make file compression more effective because common strings are repeated, but...

5. Compressed responses may not be faster

Compression algorithms such as gzip and Brotli reduce HTTP payloads by compressing data on the server before sending it to the client. This works well for static assets such as images which the server can compress once and deliver to everyone.

Compression can be less effective for smaller, data-efficient, server-rendered content which changes according to user requests (social media messages, shopping baskets, etc). A faster, less effective algorithm  --  or even no compression  --  can result in a faster response when it beats the time required to compress and decompress the data.

6. Minification may not help much

Minifying HTML, CSS, and JavaScript removes unnecessary white space, punctuation, and comments. Long JS variables such as myLongVariable are replaced with shorter options like m. This certainly helps to obfuscate code and file sizes could reduce by 20% or more. However, when combined with HTTP compression, you're unlikely to see much difference in payload sizes.

7. Multiple domains may not help performance

Developers often used to shift fixed assets such as images, fonts, and scripts to a different domain  or Content Delivery Network (CDN) . On HTTP/1.1 connections, two domains doubled the number of possible concurrent requests.

This is no longer a guaranteed performance win now HTTP/2 and HTTP/3 permit any number of requests on a single connection. Multiple domains can even affect performance because each incurs an additional DNS look-up and service workers are less able to cache responses.

8. You can load JavaScript in the HTML <head>

In the early days of the web, developers loaded <script> files in the HTML <head>. As web apps became more complex, it became more commonplace to reference those scripts before the closing </body> tag. This ensured the script didn't block the parser, the DOM tree was ready to use at the point of execution, and you weren't affected by inconsistent browser handling of defer and async.

Today, you can load JavaScript in the HTML <head> using the defer attribute. The browser defers ES6 type="module" scripts by default and runs them shortly before triggering the DOMContentLoaded event. Putting the <script> at the top of the HTML allows it to download in parallel so it's ready sooner.

If there's a technical reason that you cannot move your <script> tags, you could preload them in the HTML <head>:

<link rel="preload" href="script1.js" as="script" />
<link rel="preload" href="script2.js" as="script" />
<link rel="preload" href="script3.js" as="script" />

9. Avoid CSS @import

The CSS @import rule loads stylesheets from elsewhere but it blocks the download and parsing of all other stylesheets downloads until it's been processed. Unintuitively, it's better to use separate <link rel="stylesheet"> tags in your HTML <head> -- these will download in parallel. Alternatively, consider concatenation!

10. Self-host your fonts

Repositories such as Google Fonts make font management easier but self-hosting can provide a performance boost:

  • there's no additional DNS lookup
  • you can use a smaller set or variable font files
  • you need only load WOFF2 fonts as it's supported by all modern browsers
  • you can pre-load or lazy-load fonts as necessary
  • your won't include styles or code you're not using, and
  • there's no user tracking.

11. Avoid base64 encoding

Any binary asset such as an image or font can be base64-encoded in HTML, CSS, and JavaScript. It results in an indecipherable string of data but reduces the number of HTTP requests by encoding files inside others.

.myimg {
  background-image: url('data:image/webp;base64,abcdef0123456789etc');
}

Unfortunately:

  • base64 encoding can be 30% larger than its binary original.
  • The browser takes longer to parse and process base64 strings.
  • Multiple file requests are less expensive on HTTP/2 connections.

Only consider base64 for small assets that are unlikely to change --  perhaps something with base64 code little longer than a URL.

12. Web Workers have a performance overhead

JavaScript runs on a single processing thread. In other words, two or more scripts cannot run on the same page at the same time. This can cause a problem when you have long-running tasks such as image, audio, or video processing.

The solution is a Web Worker which allows you to run a script on a background thread separate from the main execution thread. However, Web Workers have additional overheads:

  • they take a time to load and run
  • you must stringify data passed to your worker
  • the worker can only return strings which must be decoded, and
  • they're less likely to help with mostly asynchronous processes such as fetch() requests.

13. Analytics and social media widgets harm your site

Third-party scripts look small and innocent but they can have a significant impact on performance. You've possibly added a <script> tag for analytics and sharing buttons. The tools are often free in exchange for usage and user tracking data, but they all incur performance, privacy, and security costs.

Site owners sometimes add multiple analytics scripts. The tools will return conflicting results -- not that reports are ever checked! Many browsers and add-ons block analytics and tracker scripts for privacy or performance reasons so data is possibly less accurate than you expect.

Social media sharing buttons can be worse with large payloads and intrusive processing. They're also unnecessary -- most sites provide sharing with a normal <a> link.

Assess your site by removing all third-party scripts or use CSP...

14. A Content Security Policy isn't just for security

A Content Security Policy controls whether an individual page can load specific resources. You can set them in the HTTP response header or in a meta tag in the page's HTML <head>.

The following example allows fonts, images, CSS, JavaScript, manifest files, and Ajax requests from the origin domain. It blocks all third-party assets, videos, audio, <iframe> content, and form submissions.

<meta http-equiv="Content-Security-Policy" content="
  default-src 'none';
  base-uri 'self';
  img-src 'self' data:;
  media-src 'none';
  font-src 'self';
  style-src 'self';
  script-src 'self';
  connect-src 'self';
  form-action 'none';
  frame-src 'none';
  manifest-src 'self';
">

CSP adds a level of control which prevents developers adding unapproved assets which could affect security as well as performance and privacy.

15. Be wary of performance tool results

It's easy to spoof performance results from assessment tools such as Lighthouse and PageSpeed Insights. Sneaky tricks include detecting the tool or artificially delaying heavy work. Always verify with human tests using a variety of devices, networks, and browsers.

Please contact us for performance advice if you're frustrated with your website or app.

Ready to build?

Have something complicated to build?

Tell us what you are trying to achieve, not just which page template you think you need. Whether it is a bespoke web application, a complex ecommerce build, or ongoing development support — we will tell you honestly how we can help.