Loading...

Skip to content
MemonaIQ
ToolsLearnCompany
Sign in
ToolsLearnCompanyBrowse all tools
Knowledge Center
In this topic
Performance
Core Web Vitals: what LCP, INP and CLS measureBrowser rendering: style, layout, paint and compositeHTTP caching headers: Cache-Control, ETag and 304sOptimizing web assets: images, fonts, JavaScript and CSSWeb performance metrics: TTFB, FCP, Speed Index and TBT
A-Z glossary
HomeKnowledgePerformance
Performance•4 min read•intermediate

Optimizing web assets: images, fonts, JavaScript and CSS

How to shrink and load images, fonts, JavaScript, CSS and third-party scripts: modern formats, lazy loading, font-display, code splitting and Brotli.

Where page bytes go and what to fix first

Optimizing web assets means sending fewer bytes and loading them in the right order. Images are often the largest files on a page, so start there with modern formats, the right dimensions and lazy loading below the fold. Then subset and preload fonts, split and compress JavaScript and CSS, and question every third-party script.

Measure before and after each change. The Network panel in browser developer tools shows each file's transfer size. In Chrome DevTools, the Coverage panel also shows how much of each script and stylesheet a page uses.

Images: format, dimensions and lazy loading

WebP and AVIF usually produce smaller files than JPEG and PNG at similar visual quality, and current versions of the major browsers support both. AVIF is often smaller still but slower to encode. A picture element can offer AVIF or WebP with a JPEG fallback for older browsers.

Serve images at the size they are displayed. A 4000-pixel-wide photo in a 400-pixel slot wastes most of its bytes. The srcset and sizes attributes let the browser pick the right file for the screen width and pixel density.

Add loading="lazy" to images and iframes below the fold so they load only as the user scrolls near them. Never lazy-load the main image at the top of the page, because that delays Largest Contentful Paint; give it fetchpriority="high" instead.

Set width and height attributes on every image. The browser uses them to reserve the right aspect ratio before the file arrives, which prevents layout shift, and CSS such as height: auto keeps the image responsive.

HTML Snippet
html
<!-- A below-the-fold image, so it is lazy-loaded -->
<picture>
  <source type="image/avif" sizes="(max-width: 800px) 100vw, 800px"
          srcset="/img/team-800.avif 800w, /img/team-1600.avif 1600w">
  <source type="image/webp" sizes="(max-width: 800px) 100vw, 800px"
          srcset="/img/team-800.webp 800w, /img/team-1600.webp 1600w">
  <img src="/img/team-800.jpg"
       srcset="/img/team-800.jpg 800w, /img/team-1600.jpg 1600w"
       sizes="(max-width: 800px) 100vw, 800px"
       width="800" height="533" loading="lazy"
       alt="The support team at a company meetup">
</picture>

Fonts: font-display, subsetting and preloading

Web fonts can hide text or shift the layout while they load. The font-display descriptor in @font-face controls what happens meanwhile. With swap, the browser shows a fallback font at once and switches when the web font arrives. With optional, it uses the web font only if it is available within a short block period, and otherwise keeps the fallback, which avoids a late swap.

Subset fonts to the characters you need. A font that covers many writing systems can be much larger than a Latin-only subset. With the unicode-range descriptor, the browser downloads only the subsets a page uses. Serve fonts as WOFF2, which is compressed.

Preload the one or two fonts used above the fold, so the browser fetches them before it finds them in the CSS. Font preloads need the crossorigin attribute, even for fonts on your own domain.

HTML Snippet
html
<link rel="preload" href="/fonts/inter-latin.woff2" as="font" type="font/woff2" crossorigin>
<style>
  @font-face {
    font-family: "Inter";
    src: url("/fonts/inter-latin.woff2") format("woff2");
    font-display: swap;
    unicode-range: U+0000-00FF;
  }
</style>

JavaScript and CSS: ship less, then compress it

Code splitting breaks one large bundle into smaller files, so each page loads only the code it needs. Most bundlers create a separate file for each dynamic import(), which suits features that most visitors never open, such as an editor or a chart.

Minification strips whitespace and comments and shortens names. Tree shaking removes exported code that nothing imports. Bundlers can do both in production builds, and the Coverage panel shows what is still unused. Unused CSS costs more than its size suggests, because stylesheets in the head block rendering until they load.

Compress text responses (HTML, CSS, JavaScript, JSON and SVG) with Brotli or gzip. The browser lists what it accepts in the Accept-Encoding header, and the server names its choice in Content-Encoding. Browsers offer Brotli only over HTTPS.

Brotli usually produces smaller files than gzip. Pre-compress static files at build time at the highest level, and use a faster level for responses generated per request. Skip formats that are already compressed, such as JPEG, PNG, WebP, AVIF, WOFF2 and video.

Third-party scripts

Analytics, tag managers, chat widgets, ads and embedded videos add requests to other origins and compete with your code for the main thread. You control less of their size and timing, so treat each one as a cost that has to earn its place.

Current browsers partition their HTTP cache by the site that loads a resource. A library loaded from a public CDN is downloaded again for each site that uses it, so a shared CDN copy no longer saves your visitors a download.

  • Remove scripts nobody uses anymore, including old tags left in a tag manager.
  • Load the rest with async or defer, and load chat widgets or video players only after the user interacts, behind a lightweight placeholder.
  • Add a preconnect hint for a third-party origin the page needs early, so the connection is ready when the request starts.
  • Self-host a script when its license and update process allow it, so it shares your connection and your caching rules.
Previous guide
HTTP caching headers: Cache-Control, ETag and 304s
Next guide
Web performance metrics: TTFB, FCP, Speed Index and TBT
MemonaIQ tools

Try it on your own input

Check what this guide describes against your own URL, domain, code or file.

Image Compressor

Compress JPEG, PNG, WebP and AVIF images in your browser, resize them or set a target file size. Nothing is uploaded.

Open tool
Website Launch Readiness Checker

Sign in to check a homepage before launch for uncompressed HTML, large sampled images and images missing width and height.

Open tool

References

  • MDN: Image file type and format guide
  • web.dev: Best practices for fonts
  • RFC 7932: Brotli Compressed Data Format

On this page

Where page bytes go and what to fix firstImages: format, dimensions and lazy loadingFonts: font-display, subsetting and preloadingJavaScript and CSS: ship less, then compress itThird-party scripts
Updated:2026-10-25
Format:Technical Guide
Related tool
Image Compressor

Compress JPEG, PNG, WebP and AVIF images in your browser, resize them or set a target file size. Nothing is uploaded.

Open tool
MemonaIQ

Focused tools for everyday digital work.

  • 18 focused tools
  • 9 run in your browser
Browse all tools Get help

Featured tools

URL Intelligence PlatformImage CompressorInvoice StudioDNS LookupAI Token Counter

Explore

All toolsKnowledge CenterGuidesResourcesCompany

Support

HelpContactSecurity

Legal

PrivacyTermsCookies

© 2026 MemonaIQ. Made in Colombo.

Back to top

MemonaIQ