A practical, prioritized checklist with expected impact for each step
A slow website costs you visitors, conversions, and search rankings. Google research shows that 53% of mobile visitors leave a page that takes more than 3 seconds to load. Every additional second of load time reduces conversions by roughly 7%. And since 2021, Core Web Vitals have been a direct Google ranking factor.
This is not a vague list of suggestions. It is a concrete 30-step checklist organized by category, with each step explaining what to do, why it matters, and how much improvement to expect. Work through it from top to bottom — the steps are ordered by typical impact, so the highest-return optimizations come first.
Before you start optimizing, know what you are aiming for. Google measures three Core Web Vitals:
| Metric | What It Measures | Good | Needs Improvement | Poor |
|---|---|---|---|---|
| LCP (Largest Contentful Paint) | Loading speed — how long until the main content is visible | < 2.5s | 2.5s - 4.0s | > 4.0s |
| INP (Interaction to Next Paint) | Responsiveness — how quickly the page responds to user input | < 200ms | 200ms - 500ms | > 500ms |
| CLS (Cumulative Layout Shift) | Visual stability — how much the page layout shifts while loading | < 0.1 | 0.1 - 0.25 | > 0.25 |
Check your current scores at PageSpeed Insights before starting, so you can measure your improvement.
Images are typically the heaviest resources on a page, accounting for 50-80% of total page weight. Optimizing images is almost always the single highest-impact thing you can do.
Step 1: Compress all images. Run every image through a compression tool before uploading. Lossy compression at quality 80-85 reduces file size by 40-60% with no visible difference at web resolution. Use our Image Compressor to compress images without installing software. Expected impact: 30-50% reduction in image payload.
Step 2: Convert images to WebP format. WebP delivers 25-35% smaller files than JPEG at equivalent quality, and supports transparency (unlike JPEG). All modern browsers support WebP. Use our Image Converter to convert PNG and JPEG to WebP. Expected impact: 25-35% additional image size reduction.
Step 3: Lazy load below-fold images. Add loading="lazy" to every image that is not visible in the initial viewport. This prevents the browser from downloading images the user has not scrolled to yet, dramatically reducing initial page load. Expected impact: 40-60% fewer image requests on initial load.
Step 4: Set explicit width and height on all images. Always include width and height attributes on <img> tags. This lets the browser reserve the correct space before the image loads, preventing layout shifts (CLS). Expected impact: major CLS improvement.
Step 5: Use responsive images with srcset. Serve different image sizes for different screen widths using the srcset attribute. A mobile phone does not need a 2000px-wide image. Serving a 600px version on mobile saves 70% of the file size. Use our Image Resize tool to create multiple sizes. Expected impact: 50-70% image savings on mobile.
Step 6: Serve images from a CDN. A Content Delivery Network serves images from servers geographically close to the user. This reduces latency from 200-500ms down to 20-50ms per image. Popular options include Cloudflare, BunnyCDN, and AWS CloudFront. Expected impact: 100-400ms faster image loading.
Step 7: Use the picture element for art direction. The <picture> element lets you serve completely different images based on screen size — not just different sizes of the same image. Serve a cropped, focused version on mobile and a wider version on desktop. Expected impact: better user experience plus smaller mobile payloads.
Step 8: Compress favicons and icons. Favicons and touch icons are often overlooked. A 512x512 PNG favicon can be 50-100 KB. Use SVG favicons (under 1 KB) or compress PNG icons. Expected impact: 50-100 KB savings.
After images, your CSS and JavaScript files are the next biggest opportunity for optimization.
Step 9: Minify CSS. Minification removes whitespace, comments, and unnecessary characters from CSS files. A typical CSS file shrinks 20-30% after minification. Use our Minify tool or build tools like cssnano. Expected impact: 20-30% CSS size reduction.
Step 10: Minify JavaScript. Same principle as CSS — remove whitespace, shorten variable names, and eliminate dead code. JavaScript often compresses even more than CSS, with 30-50% typical reductions. Tools include Terser, UglifyJS, or our Minify tool. Expected impact: 30-50% JS size reduction.
Step 11: Remove unused CSS. Most websites load far more CSS than any single page needs, especially when using frameworks like Bootstrap or Tailwind. Tools like PurgeCSS analyze your HTML and remove unused CSS rules. Expected impact: 50-90% CSS reduction for framework-heavy sites.
Step 12: Defer non-critical JavaScript. Add defer to script tags that are not needed for initial page render. This allows the browser to download JavaScript in parallel while continuing to parse HTML, instead of blocking rendering. Expected impact: 200-500ms faster perceived load time.
Step 13: Inline critical CSS. Extract the CSS needed to render above-fold content and inline it directly in the HTML <head>. Load the rest of the CSS asynchronously. This eliminates the render-blocking CSS request for initial content. Expected impact: 200-400ms faster first paint.
Step 14: Combine small files. Each HTTP request has overhead (DNS lookup, TCP connection, TLS handshake). If you have many small CSS or JS files (under 2 KB each), combining them into a single file reduces request overhead. With HTTP/2 this matters less, but bundling very small files still helps. Expected impact: 50-200ms improvement for sites with many small files.
Step 15: Use async for third-party scripts. Third-party scripts (analytics, chat widgets, social buttons) should never block your page. Add async to their script tags so they load independently of your page content. Expected impact: prevents 500ms-2s of blocking from third-party scripts.
Server-side optimizations reduce the time between the user's request and the first byte of your response.
Step 16: Enable Gzip or Brotli compression. Text-based resources (HTML, CSS, JS, JSON, SVG) compress dramatically with Gzip (70-80% reduction) or Brotli (75-85% reduction). Brotli is supported by all modern browsers and compresses 15-20% better than Gzip. Expected impact: 70-85% reduction in text resource transfer size.
Step 17: Set proper cache headers. Configure Cache-Control headers so browsers store static assets locally. For versioned files (e.g., styles.min.css?v=39), use max-age=31536000 (1 year). For HTML files, use shorter durations or no-cache with ETag validation. Expected impact: eliminates repeat downloads for returning visitors.
Step 18: Use HTTP/2 or HTTP/3. HTTP/2 multiplexes multiple requests over a single connection, eliminating the head-of-line blocking problem of HTTP/1.1. HTTP/3 (QUIC) further reduces latency. Most modern hosts and CDNs support HTTP/2 by default. Expected impact: 100-300ms improvement for pages with many resources.
Step 19: Reduce redirects. Each redirect adds a full round-trip to the server (100-300ms). Common unnecessary redirects include HTTP to HTTPS, www to non-www, and trailing slash redirects. Fix links to point directly to the final URL. Expected impact: 100-300ms saved per eliminated redirect.
Step 20: Use a CDN for all static assets. Serve HTML, CSS, JS, images, and fonts from a CDN. This reduces physical distance between the server and the user, cutting latency from potentially 500ms+ (cross-continent) to under 50ms. Expected impact: 100-500ms improvement for geographically distributed users.
Step 21: Optimize Time to First Byte (TTFB). TTFB should be under 200ms. If it is higher, investigate your server: check database queries, enable server-side caching (Redis, Memcached), optimize application code, or upgrade to a faster hosting provider. Expected impact: varies widely — can save 200ms to 2s depending on the bottleneck.
Web fonts are a common source of layout shifts and invisible text during loading.
Step 22: Use font-display: swap. Add font-display: swap to your @font-face rules. This tells the browser to immediately show text in a fallback font, then swap to the custom font when it loads. This prevents invisible text (FOIT) and improves perceived load time. Expected impact: eliminates invisible text, improves CLS.
Step 23: Preload critical fonts. Add <link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin> for your primary heading and body fonts. This tells the browser to start downloading the font immediately rather than waiting for CSS parsing. Expected impact: 100-300ms faster font loading.
Step 24: Limit font weights and styles. Each font weight (400, 500, 600, 700) and style (normal, italic) is a separate file download. If you load 6 weights, that is 6 file downloads. Only load the weights you actually use — most sites need at most 2-3 weights. Expected impact: 50-200 KB savings per unused weight.
Step 25: Use system fonts where possible. For body text on internal tools, admin panels, and other non-brand-critical pages, consider using the system font stack: font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif. Zero font loading time, zero layout shift. Expected impact: eliminates all font-related loading delays.
Third-party scripts are often the biggest hidden performance killer. A single chat widget or ad script can add 500ms-2s to your load time.
Step 26: Lazy load ads. Do not load ad scripts until the ad container is near the viewport. Use Intersection Observer to trigger ad loading only when the user scrolls close. Ads below the fold should never block initial page load. Expected impact: 300ms-1.5s faster initial load.
Step 27: Load analytics asynchronously. Always use the async version of analytics scripts (Google Analytics, Plausible, etc.). Place the script tag at the end of the body, not in the head. Consider lightweight alternatives — Plausible is 1 KB vs. Google Analytics at 45 KB. Expected impact: 100-300ms improvement.
Step 28: Defer chat widgets. Chat widgets (Intercom, Drift, Crisp) often load 200-500 KB of JavaScript. Defer their loading until 5-10 seconds after page load, or until the user scrolls or clicks. Most visitors do not need the chat widget in the first 5 seconds. Expected impact: 300ms-1s faster initial load.
Optimization is not a one-time task. You need to measure, monitor, and catch regressions.
Step 29: Test with PageSpeed Insights and WebPageTest. Run your key pages through PageSpeed Insights for a quick score and recommendations. For deeper analysis, use WebPageTest to see waterfall charts, filmstrip views, and performance metrics from real locations. Also use Chrome DevTools (Network tab, Performance tab, Lighthouse) for local testing. Expected impact: identifies the specific bottlenecks to fix.
Step 30: Set up ongoing monitoring. Use Google Search Console's Core Web Vitals report to track real-user metrics over time. Set up alerts in your analytics for performance regressions. Check after every deployment — a single unoptimized image or new third-party script can undo weeks of optimization work. Expected impact: prevents performance regressions.
Start with images: Compress your images, convert to WebP, and resize for responsive delivery. These three steps alone can cut your page weight by 50% or more.
Print this table or save it as a reference. Check off each step as you complete it.
| # | Step | Category | Impact |
|---|---|---|---|
| 1 | Compress all images | Images | High |
| 2 | Convert to WebP | Images | High |
| 3 | Lazy load below-fold images | Images | High |
| 4 | Set width/height on images | Images | High (CLS) |
| 5 | Use srcset for responsive images | Images | High (mobile) |
| 6 | Serve images from CDN | Images | Medium |
| 7 | Use picture element | Images | Medium |
| 8 | Compress favicons/icons | Images | Low |
| 9 | Minify CSS | Code | Medium |
| 10 | Minify JavaScript | Code | Medium |
| 11 | Remove unused CSS | Code | High |
| 12 | Defer non-critical JS | Code | High |
| 13 | Inline critical CSS | Code | Medium |
| 14 | Combine small files | Code | Low |
| 15 | Async third-party scripts | Code | High |
| 16 | Enable Gzip/Brotli | Server | High |
| 17 | Set cache headers | Server | High |
| 18 | Use HTTP/2 or HTTP/3 | Server | Medium |
| 19 | Reduce redirects | Server | Medium |
| 20 | Use CDN for static assets | Server | High |
| 21 | Optimize TTFB | Server | High |
| 22 | Use font-display: swap | Fonts | Medium (CLS) |
| 23 | Preload critical fonts | Fonts | Medium |
| 24 | Limit font weights | Fonts | Medium |
| 25 | Use system fonts where possible | Fonts | Medium |
| 26 | Lazy load ads | Third-party | High |
| 27 | Async analytics | Third-party | Medium |
| 28 | Defer chat widgets | Third-party | Medium |
| 29 | Test with PageSpeed/WebPageTest | Testing | Essential |
| 30 | Set up monitoring | Testing | Essential |
← Blog index | Image Compressor | Image Resize | Image Convert | Minify Tool | All tools