- mobile-patterns.md: Mobile layout & pattern systems (18.5KB) Fluid typography, container queries, safe-area, CSS architecture, touch-optimized components, iOS/Android specifics, testing checklist - mobile-layout-patterns.md: Mobile layout systems (11.5KB) CSS grid, single-column stack, full-bleed hero, card stack, swipeable carousel, split-screen, off-canvas nav, bottom sheet, FAB, component patterns - mobile-navigation-patterns.md: Mobile navigation (9.8KB) Bottom tab bar, top nav, hamburger menu, bottom sheet nav, pill nav, comparison matrix, navigation rules, swipe navigation, breadcrumbs, tab content - mobile-form-patterns.md: Mobile form patterns (10.3KB) Input types, keyboards, floating labels, validation patterns, progressive disclosure, autocomplete, masked inputs, toggle/radio, form anti-patterns - mobile-interaction-patterns.md: Touch & gestures (16.7KB) Swipe detection, long press, pull-to-refresh, touch feedback, scroll-reveal, parallax, sticky scroll, CSS scroll animations, touch carousel, haptic feedback, passive listeners - mobile-performance-patterns.md: Performance optimization (12.3KB) Core Web Vitals (LCP/INP/CLS), LCP optimization, INP debugging, CLS prevention, image optimization, lazy loading, service workers, CSS/JS optimization, network optimization - mobile-landing-patterns.md: Landing page patterns (21.3KB) Section sequencing, hero, social proof, feature cards, CTA patterns (inline/sticky/full-bleed), testimonials, pricing, FAQ accordion, footer, mobile checklist
12 KiB
12 KiB
title, created, updated, type, tags, sources, confidence
| title | created | updated | type | tags | sources | confidence | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Mobile Performance Patterns | 2026-07-03 | 2026-07-03 | system |
|
high |
Mobile Performance Patterns — Производительность для мобильных
1. Core Web Vitals: Мобильные Стандарты 2025/2026
1.1 Thresholds
| Метрика | Good | Needs Improvement | Poor |
|---|---|---|---|
| LCP | ≤ 2.5s | 2.5s - 4.0s | > 4.0s |
| INP | ≤ 200ms | 200ms - 500ms | > 500ms |
| CLS | ≤ 0.1 | 0.1 - 0.25 | > 0.25 |
1.2 Mobile-First Importance
На мобильных:
- LCP критичнее из-за медленных сетей (3G/4G)
- INP критичнее из-за более слабых CPU
- CLS критичнее из-за smaller viewport и layout shifts
1.3 Measurement Tools
| Tool | Purpose | Best For |
|---|---|---|
| PageSpeed Insights | Lab + Field Data | Quick audit |
| Chrome UX Report | Real user data | Production monitoring |
| Web Vitals JS Library | Runtime measurement | Dev instrumentation |
| Lighthouse | Lab testing | Development |
| DevTools Network Throttling | Simulated 3G | Testing |
2. Largest Contentful Paint (LCP)
2.1 What is LCP?
Время, когда крупнейший элемент контента (hero image, H1, section) становится видимым.
2.2 LCP Optimization Checklist
Priority:
1. Critical image — preload + next-gen format
2. Above-the-fold content — inline critical CSS
3. Server response — reduce TTFB
4. Render-blocking resources — defer/async
5. JS execution — minify + code split
2.3 Critical Image Optimization
<!-- Hero image: preload as resource -->
<link rel="preload" as="image" href="/hero-large.webp" fetchpriority="high">
<!-- Responsive hero with next-gen formats -->
<picture>
<source srcset="hero-480.webp 480w, hero-800.webp 800w, hero-1200.webp 1200w"
media="(min-width: 768px)">
<img
src="hero-480.webp"
loading="eager"
fetchpriority="high"
decoding="async"
width="800"
height="600"
alt="Hero description"
class="lcp-hero"
>
</picture>
/* Prevent layout shift for LCP image */
.lcp-hero {
width: 100%;
aspect-ratio: 16/9;
object-fit: cover;
background: color-mix(in srgb, var(--surface-2) 50%, transparent);
}
2.4 Critical CSS Inlining
<head>
<!-- Inline critical CSS (above-the-fold) -->
<style>
/* Critical path CSS — target < 14KB gzipped */
.hero {
min-height: 60vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 24px 16px;
}
.hero__title {
font-size: clamp(2rem, 8vw, 4rem);
line-height: 1.1;
margin-bottom: 16px;
}
/* ... more critical styles ... */
</style>
<!-- Defer non-critical CSS -->
<link rel="preload" href="/styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles.css"></noscript>
</head>
2.5 Reduce TTFB (Time to First Byte)
Optimization:
1. Use CDN (Cloudflare, Fastly, AWS CloudFront)
2. Edge caching (Vercel, Netlify Edge, Cloudflare Workers)
3. HTTP/2 or HTTP/3
4. Database query optimization
5. Server-side rendering (SSR) or static generation
6. Connection pooling
3. Interaction to Next Paint (INP)
3.1 What is INP?
Время между пользовательским взаимодействием и следующей отрисовкой. Заменяет FID (First Input Delay).
3.2 INP Optimization Strategies
// 1. Use passive event listeners
document.addEventListener('scroll', handler, { passive: true });
document.addEventListener('touchstart', handler, { passive: true });
// 2. Debounce expensive operations
function debounce(fn, delay = 16) {
let ticking = false;
return () => {
if (!ticking) {
requestAnimationFrame(() => {
fn();
ticking = false;
});
ticking = true;
}
};
}
// 3. Offload heavy work to Web Workers
// worker.js
self.onmessage = (e) => {
const result = heavyComputation(e.data);
self.postMessage(result);
};
/* 4. GPU-accelerated animations */
.animated-element {
will-change: transform, opacity;
transform: translateZ(0);
}
/* 5. Avoid layout thrashing */
// Bad: forces layout recalculation
element.style.width = '100px';
console.log(element.offsetWidth);
// Good: batch reads
const width = element.offsetWidth; // read
element.style.width = '100px'; // write
3.3 INP Debugging Checklist
| Category | Check | Tool |
|---|---|---|
| Event handlers | Passive listeners where possible | DevTools |
| Long tasks | < 50ms per task | DevTools Long Tasks |
| JS execution | Code splitting, tree shaking | Lighthouse |
| Layout thrashing | Batch reads/writes | DevTools |
| Main thread | No blocking scripts | Performance panel |
4. Cumulative Layout Shift (CLS)
4.1 What is CLS?
Суммарный сдвиг всех визуальных элементов за время загрузки страницы.
4.2 CLS Prevention Patterns
/* 1. Always set dimensions on images/videos */
img, video, iframe {
width: 100%;
height: auto;
object-fit: cover;
}
/* 2. Reserve space for dynamic content */
.ad-container {
min-height: 200px;
background: var(--surface-2);
}
/* 3. Font loading — prevent FOIT/FOUT */
@font-face {
font-family: 'MyFont';
src: url('/fonts/myfont.woff2') format('woff2');
font-display: swap;
}
/* 4. Sticky ads — fixed position */
.ad-sticky {
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
/* 5. Skeleton loaders */
.skeleton {
background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 4px;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
4.3 CLS Measurement
// Web Vitals library for CLS
import { getCLS } from 'web-vitals';
getCLS((value) => {
console.log('CLS:', value);
// Report to analytics
if (value > 0.25) {
sendToAnalytics('cls_threshold_exceeded', { value });
}
});
5. Image Optimization
5.1 Image Strategy for Mobile
Priority:
1. Use next-gen formats (WebP, AVIF)
2. Responsive images with srcset
3. Lazy loading for below-fold images
4. Proper dimensions (width/height)
5. Compress images (Squoosh, TinyPNG)
6. CDN for image delivery
5.2 Responsive Images Pattern
<picture>
<source srcset="image-small.webp 400w, image-medium.webp 800w, image-large.webp 1200w"
media="(min-width: 768px)">
<source srcset="image-small.avif 400w, image-medium.avif 800w, image-large.avif 1200w"
media="(min-width: 768px)">
<img
src="image-small.webp"
srcset="image-small.webp 400w, image-medium.webp 800w, image-large.webp 1200w"
sizes="(max-width: 767px) 100vw, 50vw"
loading="lazy"
decoding="async"
width="800"
height="600"
alt="Description"
class="lazy-image"
>
</picture>
5.3 Lazy Loading with Intersection Observer
class LazyLoader {
constructor(options = {}) {
this.threshold = options.threshold || 0.1;
this.rootMargin = options.rootMargin || '200px 0px';
this.observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target;
if (el.tagName === 'IMG') {
if (el.dataset.src) el.src = el.dataset.src;
if (el.dataset.srcset) el.srcset = el.dataset.srcset;
}
if (el.tagName === 'VIDEO') {
if (el.dataset.src) el.src = el.dataset.src;
}
el.classList.add('loaded');
this.observer.unobserve(el);
}
});
}, {
threshold: this.threshold,
rootMargin: this.rootMargin
});
}
observe(elements) {
elements.forEach(el => this.observer.observe(el));
}
}
// Usage
const lazyLoader = new LazyLoader({ rootMargin: '200px 0px' });
document.querySelectorAll('.lazy').forEach(el => lazyLoader.observe(el));
6. CSS & JS Optimization
6.1 CSS Optimization
/* 1. Use CSS containment */
.contained {
contain: layout style paint;
}
/* 2. Minimize reflows */
.element {
will-change: transform;
transform: translateZ(0);
}
/* 3. Use CSS variables for theming (avoids JS) */
:root {
--primary: #0070f3;
--text-primary: #111;
}
6.2 JavaScript Optimization
// 1. Code splitting
const lazyModule = import('./heavy-module.js');
// 2. Debounce user input
function debounce(fn, delay = 16) {
let ticking = false;
return () => {
if (!ticking) {
requestAnimationFrame(() => {
fn();
ticking = false;
});
ticking = true;
}
};
}
// 3. Virtual scroll for long lists
function virtualScroll(container, items, itemHeight) {
const visibleCount = Math.ceil(container.clientHeight / itemHeight);
const scrollTop = container.scrollTop;
const startIndex = Math.floor(scrollTop / itemHeight);
const endIndex = Math.min(startIndex + visibleCount + 10, items.length);
// Only render visible items
for (let i = startIndex; i < endIndex; i++) {
renderItem(items[i]);
}
}
// 4. Use requestAnimationFrame for animations
function animateElement(element, keyframes, options) {
element.animate(keyframes, {
...options,
fill: 'forwards'
});
}
7. Network Optimization
7.1 Service Worker Caching
// sw.js
const CACHE_NAME = 'mobile-app-v1';
const ASSETS_TO_CACHE = [
'/',
'/styles.css',
'/app.js',
'/fonts/*'
];
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => cache.addAll(ASSETS_TO_CACHE))
);
});
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
7.2 Prefetch & Preconnect
<!-- Preconnect to critical origins -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://api.example.com">
<!-- Prefetch critical resources -->
<link rel="prefetch" href="/next-page.js">
<link rel="prefetch" href="/critical-image.webp">
<!-- Preload critical resources -->
<link rel="preload" href="/hero-large.webp" as="image" fetchpriority="high">
8. Mobile Performance Checklist
| Metric | Target | Tool |
|---|---|---|
| LCP | ≤ 2.5s | PageSpeed Insights |
| INP | ≤ 200ms | Web Vitals JS |
| CLS | ≤ 0.1 | PageSpeed Insights |
| FCP | ≤ 1.8s | DevTools |
| TTFB | ≤ 600ms | Network panel |
| Total JS | ≤ 200KB | Lighthouse |
| Total CSS | ≤ 50KB (critical) | Lighthouse |
| Images | Next-gen + responsive | PageSpeed Insights |
9. Mobile Performance Anti-Patterns
| ❌ Плохо | ✅ Хорошо |
|---|---|
| 100vh для полноэкранных секций | 100dvh |
| Полноэкранные изображения | Responsive images + lazy loading |
| Тяжелые JS-библиотеки | Vanilla JS / lightweight alternatives |
| Автоплей видео | Play/pause по тапу |
| Шрифты без font-display | font-display: swap |
| Без сжатия изображений | WebP/AVIF + compression |
| Синхронный JS в <head> | Async/defer |