A fast website on a phone: how I raised the score from 61 to 93

Case study: main content visible after 2.5 s instead of 5.8 s, a page without layout jumps and a weight cut from 3 MB to 0.5 MB. Concrete causes and fixes.

Illustration: a phone with a website and a speed gauge
AI-generated illustration

I design fast websites, so it’s only right that my own should be fast. Yet the measurement in Google PageSpeed Insights showed 61–70 points on a phone, and the main content only appeared after 5.8 seconds. On a computer it was fine, but most people visit websites from a phone.

Below I describe exactly what was slowing the website down and how I fixed it. The problems I found occur on very many business websites, including those built on WordPress.

Result: before and after

Metric (phone) Before After
PageSpeed score 61–70 88–98 (median about 93)
Main content (LCP) 5.8 s 2.3–2.9 s
Layout shift (CLS) 0.044–0.114 0
First paint (FCP) 3.0–3.8 s 1.7–2.1 s
Page weight 2.96 MB 0.51 MB

On a computer the website now scores 100 points. All of this without removing the animations and without giving up the interactive editor at the top of the page.

Step 0: measure before you start fixing

PageSpeed Insights simulates a mid-range phone on a slow mobile connection. It is a good approximation, but the number of points alone says little. The key question is: which element does Google treat as the main content, and why does it appear so late?

The answer surprised me. Google wasn’t measuring the page heading but a photo in the editor demo, which appeared after about 6 seconds. The file downloaded instantly, but the website-building animation revealed it only after a longer while. Without a detailed measurement I would have looked for the problem in a completely different place.

1. An animation that delayed the main content

Google treats the largest element visible on the screen as the main content (LCP). If something large appears late, even as part of an impressive animation, the whole score drops.

On my website two things added up to this:

  • The website-building demo started too early. On a phone it began when 75% of the editor was still below the screen. Now it starts when the editor slides in to roughly the middle of the screen. This is better for the visitor too, because they see the whole building process and not just its ending.
  • To Google, the heading was several small pieces. Each line of the heading was a separate block, and the animation additionally split it into single words. For Google that is a dozen or so small elements instead of one large one. After the change the heading is a single block of text and counts from the first moment.

I also moved the entrance animation from JavaScript to CSS. Previously the content appeared, disappeared after the scripts loaded and slid in again. Now the animation starts together with the first paint of the page, and the heading sharpens into focus instead of fading in from transparency.

2. Layout jumps while fonts load

The website uses two fonts: the sans-serif Geist and the decorative italic Cormorant. Before they download, the browser shows the text in a fallback font, e.g. Arial. The fallback italic was 17% wider than the real one, so the heading wrapped differently, and after the font swap all the content below it jumped.

The solution is fallback fonts with matched dimensions. CSS lets you scale Arial and Times New Roman so that they take up the same space as the real fonts (the properties size-adjust, ascent-override and descent-override). I measured both fonts and the width difference dropped from 17% to 2%. The layout shift dropped to zero.

3. Too many files blocking the first paint

Before the browser shows anything, it has to download all the stylesheets from the page header. I had five of them: the page styles, the fonts, two icon sets and the smooth-scrolling styles. On a slow connection every file is a separate delay.

The fixes:

  • One CSS file instead of five. The merging happens automatically when the website is published, and in the source code the files are still separate.
  • Scripts with the defer attribute. They download in parallel and run in the same order, but they don’t hold up the first paint.
  • Chat styles loaded in the background. The chat button appears only after the scripts load anyway.

4. Icons: 1,500 in the file, 135 in use

The icons on the website come from the Phosphor library, loaded as a font. The full files contained about 1,500 icons and weighed 280 KB together. I use 135.

On publishing, the website finds the icons in use by itself and trims the style files and the fonts down to them. 28 KB remained, ten times less. The icons look the same, and if I add a new one, it goes into the file automatically at the next publish.

5. Photos: the right size and format

This is the most common problem on business websites, and on mine it was the biggest too:

  • The photos in the cards were 1,440 px wide, but they were displayed in frames 285–557 px wide. Now the cards get WebP versions 800 px wide. Large cards can still reach for the full photo through the srcset attribute when the screen has a high resolution. The project photos alone shrank from 2.9 MB to 0.9 MB.
  • Lazy loading doesn’t always work. The photos had loading="lazy", but the browser downloaded them right away anyway. In the first page layout, before the scripts built the sections above them, they were close to the top of the page. The solution was to shrink the files and to deliberately control when each thing loads.
  • The demo downloaded photos for five industries in advance. Now it downloads the photos of the current industry just before the build, and the rest only when the showcase actually switches industries. The saving: about 1.6 MB on every visit.

Bonus: the page scrolled by itself on refresh

Along the way a small but irritating bug turned up: after a refresh the page opened slightly scrolled down. The browser remembers the scroll position relative to a specific element. On my website the scripts build half of the page after loading, so that element ended up lower and the page jumped by 80–180 px.

Now a refresh always starts at the top, and the “Back” button returns to exactly the same place, because the page remembers the position itself.

What this means for your website

On the business websites I check, the same causes repeat most often:

  1. Photos straight from a camera or stock sites, several megabytes each, instead of files matched to their place on the page.
  2. A slider or video at the top of the page, which appears with a delay and becomes the main content in Google’s eyes.
  3. A heavy theme and a dozen or so plugins, each adding its own styles and scripts on every subpage.
  4. Several font types without matched fallbacks, so the text jumps.
  5. No measurement. Without checking which element is the main content, it is easy to fix the wrong thing.

The check takes half a minute: enter your address in the Check your website tool and you get Google’s speed score together with a list of concrete causes.

How much does speeding up a website cost

Minor fixes, such as compressing photos, tidying up plugins and adjusting server settings, I do as part of technical maintenance from PLN 149 a month. When the website sits on a heavy theme and the fixes would cost more than a new version, website redesign costs from PLN 2,900. All prices are net.

Let’s check your website

Check your website for free and send me the report from below the result, or write via the form. I’ll reply within 24 hours with what is slowing the website down and how much the improvement costs. New customers get a 20% discount on their first project.

Frequently asked questions

Related services

Have a similar project?

Describe what you need and I’ll send a quote within 24 hours. New clients get 20% off their first project.

Get a quoteBook a call (20 min)

Read more

Websites1 November 202610 min read

Restaurant website: menu and online orders

What a restaurant or pizzeria website needs: a text menu, 14 allergens for online orders, your own orders next to the portals and a Google Business Profile.