
Web Vitals patterns
This collection includes patterns that are often tricky to implement without hurting your Core Web Vitals scores. Use the code in these examples to help ensure your projects stay on the right track.
- How to query the Web Platform Dashboard for Baseline tooling
- Core Web Vitals workflows with Google tools
- February 2025 Baseline monthly digest
- ruby-align is Baseline Newly available
- Download AI models with the Background Fetch API
- Prefetch resources to speed up future navigations
- Optimize Cumulative Layout Shift
- Debug layout shifts
- CSS scrollbar-gutter and scrollbar-width are Baseline Newly available
- January 2025 Baseline monthly digest
- Scaling multithreaded WebAssembly applications with mimalloc and WasmFS
- WasmGC and Wasm tail call optimizations are now Baseline Newly available
- Largest Contentful Paint (LCP)
- Time to First Byte (TTFB)
- Promise.try is now Baseline Newly available
- Simpler WebAuthn feature detection with getClientCapabilities()
- Build local and offline-capable chatbots
- Optimize long tasks
- Setting up a payment method
- Apply effects to images with the CSS mask-image property
- Baseline 2024: more tools to help web developers
- Lazy loading video
- Preload modules
- Measure browser autofill on your forms
- Part 2: Build client-side AI toxicity detection
- Total Blocking Time (TBT)
- Getting started with measuring Web Vitals
- The most effective ways to improve Core Web Vitals
- Optimize Largest Contentful Paint
- Web Vitals
- The CSS content-visibility property is now Baseline Newly available
- How the Core Web Vitals metrics thresholds were defined
- Manually diagnose slow interactions in the lab
- Baseline
- Back/forward cache
- CSS nesting improves with CSSNestedDeclarations
- Debug performance in the field
- First Input Delay (FID)
- Benchmarking the performance of CSS @property
- Correlating Core Web Vitals and ad revenue with Google tools
- Storage for the web
- It's time to lazy-load offscreen iframes!
- Building multiple Progressive Web Apps on the same domain
- The Web Push Protocol
- How Chrome handles updates to the web app manifest
- What makes a good Progressive Web App?
- What does it take to be installable?
- Add a web app manifest
- Mitigate cross-site scripting (XSS) with a strict Content Security Policy (CSP)
- Accessing hardware devices on the web
- Allow passkey reuse across your sites with Related Origin Requests
- Browser-level image lazy loading for the web
- Choose the right image format
- Custom metrics
- Measure and debug performance with Google Analytics 4 and BigQuery
- Web permissions best practices
- Best practices for cookie notices
- Customize media notifications and playback controls with the Media Session API
- Find slow interactions in the field
- Using tabindex
- Practical prompt engineering for smaller LLMs
- Interaction to Next Paint (INP)
- CSS color-scheme-dependent colors with light-dark()
- WebAssembly performance patterns for web apps
- CSS animated grid layouts
- Play the Chrome dino game with your gamepad
- The inert attribute
- Determine the passkey provider with AAGUID
- Compiling to and optimizing Wasm with Binaryen
- Capture audio and video in HTML5
- The <model-viewer> web component
- userVerification deep dive
- Why is CrUX data different from my RUM data?
- Accessibility for web developers
- Load Third-Party JavaScript
- Prevent creation of a new passkey if one already exists
- Work with IndexedDB
- 5 CSS snippets every front-end developer should know in 2024
- Optimize Time to First Byte
- What are the parts of a URL?
- Discoverable credentials deep dive
- Rendering performance
- ResizeObserver: it's like document.onresize for elements
- Optimize the encoding and transfer size of text-based assets
- OffscreenCanvas—speed up your canvas operations with a web worker
- First Contentful Paint (FCP)
- Content delivery networks (CDNs)
- What makes for a good sign-out experience?
- Time to Interactive (TTI)
- Optimize resource loading with the Fetch Priority API
- The :user-valid and :user-invalid pseudo-classes
- Optimize Core Web Vitals for business decision makers
- The nuances of base64 encoding strings in JavaScript
- CSS subgrid
- Effectively loading ads without impacting page speed
- Four common types of code coverage
- To test or not to test, a technical perspective
- Defining test cases and priorities
- User-centric performance metrics
- Preload responsive images
- Adapting typography to user preferences with CSS
- Pyramid or Crab? Find a testing strategy that fits
- Three common types of test automation
- Eliminating Unnecessary Downloads
- What is WebAssembly and where did it come from?
- Compiling mkbitmap to WebAssembly
- Securely hosting user data in modern web applications
- The origin private file system
- Deploying AVIF for more responsive websites
- Optimize Interaction to Next Paint
- Baseline features you can use today
- Script evaluation and long tasks
- Client-side rendering of HTML and interactivity
- Optimize input delay
- How large DOM sizes affect interactivity, and what you can do about it
- Build in-browser WordPress experiences with WordPress Playground and WebAssembly
- Cumulative Layout Shift (CLS)
- New functionality for developers—brought to you by WebAssembly
- What are source maps?
- PWAs in app stores
- 6 CSS snippets every front-end developer should know in 2023
- Trigonometric functions in CSS
- Perform efficient per-video-frame operations on video with requestVideoFrameCallback()
- GDE community highlight: Lars Knudsen
- New patterns for media apps
- Speedy CSS Tip! Animated Gradient Text
- Building Chrometober!
- Building a tooltip component
- Create a passkey for passwordless logins
- Sign in with a passkey through form autofill
- Building a floating action button (FAB) component
- Best practices for fonts
- GDE community highlight: Alba Silvente Fuentes
- Speedy CSS Tip! Animated Loader
- Testing Web Design Color Contrast
- Building the main navigation for a website
- Is it :modal?
- Building a crooked grid illusion
- Best practices for tags and tag managers
- Creative list styling
- How Nordhealth uses Custom Properties in Web Components
- Finer grained control over CSS transforms with individual transform properties
- CSS border animations
- New patterns
- How the BBC is rolling out HSTS for better security and performance.
- Why lab and field data can be different (and what to do about it)
- A win-win situation
- The end of Internet Explorer
- Farewell to HTML5Rocks
- First-party cookie recipes
- Synchronize audio and video playback on the web
- Use conic gradients to create a cool border
- Implement error handling when using the Fetch API
- Choose a JavaScript library or framework
- The difference between JavaScript libraries and frameworks
- The Front-End Developer's Guide to the Terminal
- An API for fast, beautiful web fonts
- GOV.UK drops jQuery from their front end.
- Building a button component
- Don't fight the browser preload scanner
- Best practices for measuring Web Vitals in the field
- Bridging the gap
- Finding courage and inspiration in the developer community
- Variable fonts in real life
- Quickly create nice CSS gradients with the CSS Gradient Creator
- Deep dive into top web developer pain points
- Make your site picture perfect with images.tooling.report
- Global and local variable scope
- Building a dialog component
- Debug media playback errors on the web
- GDE community highlight: Nishu Goel
- The performance effects of too much lazy loading
- Building a loading bar component
- Save Credentials from Forms
- Chrome and Firefox soon to reach major version 100
- Building an adaptive favicon
- Drawing to canvas in Emscripten
- Improve security and privacy by updating HTTP Cache
- Additional HTML elements
- Porting USB applications to the web. Part 2: gPhoto2
- Network Error Logging (NEL)
- WebAssembly feature detection
- Porting USB applications to the web. Part 1: libusb
- Building a theme switch component
- Embedding JavaScript snippets in C++ with Emscripten
- PWAs on Oculus Quest 2
- Building Designcember
- Designcember Calculator
- Deep-copying in JavaScript using structuredClone
- Building a toast component
- The UI fund
- Building a 3D game menu component
- Towards an animation smoothness metric
- What's new in PageSpeed Insights
- Everything announced at Chrome Dev Summit 2021
- Lighthouse user flows
- Photoshop's journey to the web
- Building a multi-select component
- How to assess loading performance in the field with Navigation Timing and Resource Timing
- Safe DOM manipulation with the Sanitizer API
- Best practices for using third-party embeds
- How SPA architectures affect Core Web Vitals
- JavaScript eventing deep dive
- Bundling non-JavaScript resources
- Building a split-button component
- Using CSS Module Scripts to import stylesheets
- Building a switch component
- CSS accent-color
- User preference media features client hints headers
- Building a breadcrumbs component
- Using WebAssembly threads from C, C++ and Rust
- Media encryption
- Media streaming basics
- Media frameworks
- PWA with offline streaming
- Building a color scheme
- CSS size-adjust for @font-face
- Using AVIF to compress images on your site
- CSS for Web Vitals
- Evolving Cumulative Layout Shift in web tooling
- New CSS functional pseudo-class selectors :is() and :where()
- New Progressive Web App training now available
- Migrate to User-Agent Client Hints
- The new responsive: Web design in a component-driven world
- Excalidraw and Fugu: Improving Core User Journeys
- Security headers quick reference
- ES modules in service workers
- Building a media scroller component
- Optimizing Web Vitals using Lighthouse
- Using asynchronous web APIs from WebAssembly
- Keeping third-party scripts under control
- Customize the window controls overlay of your PWA's title bar
- Breaking down barriers using the DataTransfer API
- Fill OTP forms within cross-origin iframes with WebOTP API
- Building split text animations
- Evolving the CLS metric
- Web Developer Satisfaction
- Building a Settings component
- JavaScript: What is the meaning of this?
- Mini apps and super apps
- Mini app components
- What are H5 and QuickApp?
- What are mini apps?
- Other mini app runtime environments
- Mini app markup, styling, scripting, and updating
- Applying the mini app programming principles to an example project
- Mini app open source projects
- Project structure, lifecycle, and bundling
- Mini app DevTools
- Concluding thoughts about mini apps from a web developer
- Programming the mini app way
- Mini app standardization
- Streams—The definitive guide
- Building a Tabs component
- A guide to enable cross-origin isolation
- Requesting performance isolation with the Origin-Agent-Cluster header
- The CSS aspect-ratio property
- WebRTC is now a W3C and IETF standard
- Best practices for carousels
- Use HTTPS for local development
- Feedback wanted: The road to a better layout shift metric for long-lived pages
- When to use HTTPS for local development
- Building a sidenav component
- Codelab: Building a Sidenav component
- Centering in CSS
- Codelab: Centering in CSS
- Love your cache ❤️
- Cross-browser paint worklets and Houdini.how
- Address form best practices codelab
- Payment and address form best practices
- Sign-up form best practices
- Sign-up form best practices codelab
- SMS OTP form best practices
- Payment form best practices codelab
- Automating audits with AutoWebPerf
- Two-way communication with service workers
- Broadcast updates to pages with service workers
- Imperative caching guide
- Workers overview
- Disable mouse acceleration to provide a better FPS gaming experience
- Codelab: Building a Stories component
- Building a Stories component
- Schemeful Same-Site
- Browser-level lazy loading for CMSs
- Codelab: Build a push notification server
- Codelab: Build a push notification client
- Push notifications overview
- Measuring offline usage
- Examples of high-performance CSS animations
- Signed Exchanges (SXGs)
- CSS min(), max(), and clamp()
- Logical layout enhancements with flow-relative shorthands
- Handling range requests in a service worker
- Why are some animations slow?
- How to create high-performance CSS animations
- Control camera pan, tilt, and zoom
- What are third-party origin trials?
- Detached window memory leaks
- Create an offline fallback page
- Core Web Vitals
- Create interesting image shapes with CSS's clip-path property
- Custom bullets with CSS ::marker
- Help users change passwords easily by adding a well-known URL for changing passwords
- Orchestrating payment transactions with a service worker
- Handling optional payment information with a service worker
- ARIA: poison or antidote?
- Debugging memory leaks in WebAssembly using Emscripten
- content-visibility: the new CSS property that boosts your rendering performance
- Unblocking clipboard access
- Web on Android
- Referer and Referrer-Policy best practices
- Building a PWA at Google, part 1
- Performance monitoring with Lighthouse CI
- Designing the user experience of passkeys on Google accounts
- @property: giving superpowers to CSS variables
- Web-based payment apps overview
- Relating site speed and business metrics
- Service worker caching and HTTP caching
- Registering a web-based payment app
- Providing shipping and contact information from an Android payment app
- Handling navigation requests
- Using the Chrome UX Report to look at performance in the field
- Pixel-perfect rendering with devicePixelContentBox
- Ten modern layouts in one line of CSS
- web.dev LIVE wrap-up
- Progressively enhance your Progressive Web App
- Use cross-platform browser features to build a sign-in form
- Sign-in form best practices
- Web developer tools for debugging JavaScript issues in Google Search
- Building resilient search experiences with Workbox
- Add media to a web page
- Media file basics
- Boldly link where no one has linked before: Text Fragments
- How to file a good browser bug
- Make your PWA feel more like an app
- Measure performance with the RAIL model
- Speed up navigations in React with Quicklink
- Protect your resources from web attacks with Fetch Metadata
- Content reordering
- Web Animations API improvements in Chromium 84
- Life of a payment transaction
- Android payment app developers guide
- Empowering payment apps with Web Payments
- More variable font options for the macOS system-ui font in Chromium 83
- How Progressive Web Apps can drive business success
- Get things done quickly with app shortcuts
- Preparing for AppCache removal
- How to define your install strategy
- Persistent storage
- How CommonJS is making your bundles larger
- Why you need "cross-origin isolated" for powerful features
- Profiling Web Audio apps in Chrome
- Improved Next.js and Gatsby page load performance with granular chunking
- "Same-site" and "same-origin"
- Monitor your web page's total memory usage with measureUserAgentSpecificMemory()
- Making your website "cross-origin isolated" using COOP and COEP
- web.dev engineering blog #1: How we build the site and use Web Components
- Improved dark mode default styling with the color-scheme CSS property and the corresponding meta tag
- Ensure your website is available and usable for everyone during COVID-19
- Fix an overloaded server
- Accessible responsive design
- Color and contrast accessibility
- Accessible tap targets
- Prevent DOM-based cross-site scripting vulnerabilities with Trusted Types
- Using a PWA in your Android app
- Prevent layout shifting and flashes of invisible text (FOIT) by preloading optional fonts
- How to set up Signed HTTP Exchanges (SXG) using nginx
- How to distribute Signed HTTP Exchanges (SXG) using nginx
- Optimize CSS background images with media queries
- Fixing website speed cross-functionally
- Scroll snapping after layout changes
- How to set up Signed Exchanges using Web Packager
- How to provide your own in-app install experience
- Positioning virtual objects in real-world views
- Augmented reality: You may already know it
- Virtual reality comes to the web, part II
- Advancing the web framework ecosystem
- What are Progressive Web Apps?
- Integrate PWAs into built-in sharing UIs with Workbox
- Adaptive icon support in PWAs with maskable icons
- Improving page dismissal in synchronous XMLHttpRequest()
- Threading the web with module workers
- Adaptive loading: improving web performance on slow devices
- Speed tooling evolutions: highlights from Chrome Developer Summit 2019
- Use web workers to run JavaScript off the browser's main thread
- Feedback from the summer 2019 image optimization survey
- Build a push notifications server
- How AMP can guarantee fastness in your Next.js app
- Code splitting with dynamic imports in Next.js
- Integrate with the OS sharing UI with the Web Share API
- Performance as a default with Next.js
- Route prefetching in Next.js
- Virtual reality comes to the web
- SameSite cookie recipes
- Understanding cookies
- Fast ads matter
- Use push notifications to engage and re-engage users
- Get started with the Notifications API
- Use a Service Worker to manage notifications
- Fixing layout instability
- Techniques to make a web app load fast, even on a feature phone
- Smarter custom properties with Houdini’s new API
- Two ways to prefetch: <link> tags and HTTP headers
- Fixing mixed content
- What is mixed content?
- Going beyond images with basic video for the web
- Add an Apple touch icon to your Progressive Web App
- Ready Player Web
- Progressive Web Apps in multi-origin sites
- Reduce web font size
- Optimize WebFont loading and rendering
- Create a Progressive Web App with the Angular CLI
- Use image CDNs to optimize images
- Identify slow third-party JavaScript
- Efficiently load third-party JavaScript
- Third-party JavaScript performance
- More capable form controls
- Optimize third-party JavaScript
- Establish network connections early to improve perceived page speed
- Create OS-style backgrounds with backdrop-filter
- Keeping things fresh with stale-while-revalidate
- Virtualize large lists with the Angular CDK
- Route preloading strategies in Angular
- Optimize Angular's change detection
- Adapt video to image serving based on network quality
- Faster web navigation with predictive prefetching
- Audit your Angular app's accessibility with codelyzer
- Precaching with the Angular service worker
- Performance budgets with the Angular CLI
- prefers-color-scheme: Hello darkness, my old friend
- Route-level code splitting in Angular
- Get started: optimize an Angular application
- Top tips for web performance
- Web components: the secret ingredient helping power the web
- Use Lighthouse for performance budgets
- Updates to the Web Payments APIs
- The value of speed
- Address Bar Install for Progressive Web Apps on the Desktop
- How can performance improve conversion?
- How do I notify users that my PWA is installable?
- Patterns for promoting PWA installation
- Service worker mindset
- Image policies for fast load times and more
- Extract critical CSS
- Are long JavaScript tasks delaying your Time to Interactive?
- Extract and inline critical CSS with Critical
- Speed at scale: what's new in web performance?
- Introducing PROXX
- SameSite cookies explained
- Visual searching with the Web Perception Toolkit
- Hands-on with Portals: seamless navigation on the web
- Adaptive serving based on network quality
- Minify and compress network payloads with brotli
- web.dev at I/O 2019
- How to stay fast?
- What is speed?
- How to measure speed?
- Add a web app manifest with Create React App
- Get started: optimize your React app
- Pre-render routes with react-snap
- Code splitting with React.lazy and Suspense
- Virtualize large lists with react-window
- Precaching in Create React App with Workbox
- Accessibility audit with react-axe and eslint-plugin-jsx-a11y
- Codelab: Preload critical assets to improve loading speed
- prefers-reduced-motion: Sometimes less movement is more
- Defer non-critical CSS
- Trust is good, observation is better: Intersection Observer v2
- Responsive web design basics
- Constructable Stylesheets
- Rendering on the Web
- Incorporate performance budgets into your build process
- Using bundlesize with Travis CI
- Setting performance budgets with webpack
- Using Lighthouse Bot to set a performance budget
- Emscripten and npm
- Is your app installed? getInstalledRelatedApps() will tell you!
- Adapting to Users with Client Hints
- Keyboard access fundamentals
- Control focus with tabindex
- Headings and landmarks
- Labels and text alternatives
- Use semantic HTML for easy keyboard wins
- Style focus
- Semantics and screen readers
- What is accessibility?
- Explore DevTools Network panel
- Specifying multiple slot widths
- Replace GIFs with video
- Reduce JavaScript payloads with code splitting
- Same Origin Policy & Fetch requests
- Creating WebP Images with the Command Line
- How to measure search engine optimization with Lighthouse
- Using Imagemin with webpack
- Serve images with correct dimensions
- Replace animated GIFs with video for faster page loads
- How search works
- Remove unused code
- Apply instant loading with the PRPL pattern
- Identify resources loaded from the network