بهینهسازی مدرن تصاویر وب در ۲۰۲۶: راهنمای عملی AVIF، WebP و Responsive Images
راهنمای عملی بهینهسازی تصاویر مدرن وب با AVIF، WebP و srcset. تنظیم fetchpriority برای LCP، جلوگیری از CLS با width/height صریح، و کاهش ۵۰٪ حجم فایل با نمونه کد sharp و الگوی picture.
بهینهسازی مدرن تصاویر وب یعنی ارسال فرمت درست (AVIF با fallback به WebP و JPEG)، در وضوح متناسب با دستگاه (srcset و sizes)، با سیگنالهای اولویت صحیح (fetchpriority="high" برای LCP و loading="lazy" برای بقیه) و ابعاد صریح برای جلوگیری از Layout Shift. طبق دادههای HTTP Archive در ۲۰۲۶، تصاویر ۴۸٪ از وزن صفحه و در حدود ۸۵٪ از عناصر LCP دسکتاپ را تشکیل میدهند؛ به همین دلیل بهینهسازی تصاویر همچنان پرسودترین بهبود عملکرد در پروژههای وب است.
AVIF در سال ۲۰۲۶ به پشتیبانی ۹۴٫۹٪ رسیده و در همان کیفیت تا ۵۰٪ کوچکتر از JPEG و ۲۰–۲۵٪ کوچکتر از WebP است؛ WebP با ۹۶٫۴٪ پشتیبانی fallback ایمنی است.
افزودن تنها یک ویژگی fetchpriority="high" به تصویر LCP در تستهای گوگل زمان بارگذاری را از ۲٫۶ ثانیه به ۱٫۹ ثانیه رساند (بهبود ۲۷٪).
تصاویر پایین صفحه را با loading="lazy" بارگذاری کنید، اما هرگز تصویر LCP را lazy نکنید. این کار مستقیماً معیار Core Web Vitals را از بین میبرد.
تعیین صریح width و height در HTML باعث رزرو فضا و جلوگیری از افزایش CLS میشود.
الگوی <picture> با fallback خودکار AVIF → WebP → JPEG، بدون یک خط جاوااسکریپت و سازگار با هر CDN، بهترین روش پیادهسازی است.
چرا بهینهسازی تصاویر مهمترین اهرم عملکرد است؟
راستش را بخواهید، وقتی به بودجه بایتی یک صفحه معمولی نگاه میکنید، تصاویر معمولاً بزرگترین قسمت کیک هستند. طبق دادههای Web Almanac در ۲۰۲۶، میانگین وزن تصاویر یک صفحه دسکتاپ حدود ۹۸۰ کیلوبایت است، یعنی تقریباً نیمی از کل ترافیک صفحه. مهمتر از آن، در حدود ۸۵٪ از صفحات دسکتاپ عنصر Largest Contentful Paint یک تصویر (هیرو، بنر، پسزمینه <img>) است. یعنی اگر فقط روی یک چیز کار کنید تا Core Web Vitals را بهبود دهید، آن یک چیز باید تصاویر باشد.
در راهنمای بهینهسازی LCP و بارگذاری محتوای اصلی نشان دادیم که مسیر بحرانی رندر تقریباً همیشه از یک تصویر میگذرد. در راهنمای بهینهسازی CLS و پایداری بصری هم دیدیم که تصاویر بدون ابعاد صریح، بزرگترین متهم پرشهای چیدمان هستند. بهینهسازی مدرن تصویر چهار حوزه همپوشان دارد: انتخاب فرمت (AVIF، WebP، JPEG)، واریانتهای واکنشگرا (srcset و sizes)، سیگنال اولویت (fetchpriority و loading) و رزرو چیدمان (width و height صریح). یک صفحه که هر چهار مورد را درست انجام میدهد معمولاً LCP خود را ۴۰ تا ۷۰ درصد کاهش میدهد.
AVIF در برابر WebP: کدام فرمت را در ۲۰۲۶ انتخاب کنیم؟
پاسخ کوتاه: هر دو را ارائه دهید. AVIF (فرمت تصویر مبتنی بر کدک ویدیویی AV1، منتشرشده در ۲۰۱۹ توسط Alliance for Open Media) در ۲۰۲۶ به پشتیبانی جهانی ۹۴٫۹٪ رسیده و برای همان کیفیت بصری تا ۵۰٪ کوچکتر از JPEG و ۲۰–۲۵٪ کوچکتر از WebP است. WebP با ۹۶٫۴٪ پشتیبانی، سرعت decode بالاتری در سمت مرورگر دارد و بهعنوان fallback ایدهآل عمل میکند. JPEG یا PNG هم بهعنوان لایه سوم برای مرورگرهای بسیار قدیمی یا شرایط خاص (مثلاً print CSS) باقی میماند.
ویژگی
AVIF
WebP
JPEG
پشتیبانی جهانی مرورگر (۲۰۲۶)
۹۴٫۹٪
۹۶٫۴٪
۱۰۰٪
کاهش اندازه فایل نسبت به JPEG
~۵۰٪
~۳۰٪
مبنا
پشتیبانی از شفافیت (alpha)
بله
بله
خیر
پشتیبانی HDR و 10/12-bit
بله
خیر
خیر
سرعت decode روی CPU متوسط
متوسط
سریع
خیلی سریع
کیفیت پیشنهادی برای وب
۶۰–۷۰
۷۵–۸۵
۸۰–۸۵
مورد استفاده معمول
لایه اول
Fallback میانی
Fallback نهایی
برای عکسهای خیلی کوچک (کمتر از ۱۰ کیلوبایت) هزینه سربار AVIF ممکن است بهرهوری آن را از بین ببرد؛ برای گرافیکهای وکتوری و آیکنها همچنان SVG بهترین انتخاب است. اما برای هر تصویر content که بالای ۱۵ کیلوبایت باشد، ارائه AVIF یک برد قطعی است.
الگوی <picture>: پیادهسازی fallback بدون جاوااسکریپت
عنصر <picture> به مرورگر اجازه میدهد اولین <source> پشتیبانیشده را انتخاب کند و بقیه را نادیده بگیرد. الگوی استاندارد در ۲۰۲۶ به این شکل است:
ترتیب مهم است: AVIF باید قبل از WebP باشد؛ مرورگر اولین فرمت پشتیبانیشده را انتخاب میکند و بقیه را رد میکند.
تگ <img> اجباری است: اگر آن را حذف کنید هیچ چیز نمایش داده نمیشود. این تگ حاوی fallback نهایی (JPEG/PNG) و همه سیگنالها (alt، width، height، fetchpriority، loading) است.
ویژگیها روی <img>: برخلاف تصور رایج، fetchpriority و loading را باید روی خود <img> بگذارید نه روی <source>. حتی اگر مرورگر AVIF را از source بارگذاری کند، این ویژگیها اعمال میشوند.
alt همچنان اجباری است: برای دسترسپذیری و SEO. اگر تصویر صرفاً تزیینی است از alt="" استفاده کنید.
تصاویر واکنشگرا با srcset و sizes چگونه کار میکنند؟
ارسال یک تصویر ۱۲۰۰ پیکسلی به گوشی موبایل با عرض ۴۰۰ پیکسل، ۳ برابر بیش از حد داده است. ویژگی srcset به مرورگر لیستی از گزینهها میدهد و sizes توضیح میدهد که تصویر در چیدمان چه فضایی میگیرد. مرورگر با ترکیب این دو مورد بهعلاوه Device Pixel Ratio، بهترین اندازه را انتخاب میکند.
در این مثال، مرورگر میفهمد که در گوشی تصویر ۱۰۰٪ عرض viewport را میگیرد، در تبلت ۵۰٪، و در دسکتاپ ۳۳٪. سپس با ضرب در DPR (مثلاً ۲x در Retina) نزدیکترین گزینه srcset را انتخاب میکند. برای یک گوشی ۴۰۰px با DPR=۳، مرورگر معمولاً نسخه ۱۲۰۰w را میخواهد.
قانون ۱٫۵x: چند اندازه srcset تولید کنیم؟
تولید ۱۰ اندازه مختلف اسراف است. قاعدهی رایج ۱٫۵x است: هر گام باید حداقل ۱٫۵ برابر گام قبلی باشد. برای بیشتر پروژهها، این ۴ اندازه کافی است: 400w، 800w، 1200w، 1800w. اگر تصاویر شما هرگز از ۹۰۰px عریضتر نیستند، حتی سه اندازه (۴۰۰/۶۰۰/۹۰۰) بس است.
چگونه fetchpriority را برای تصویر LCP تنظیم کنیم؟
ویژگی fetchpriority یک «راهنمایی» به مرورگر است که میگوید این منبع را با اولویت بالا (high)، پایین (low) یا خودکار (auto) بارگذاری کند. طبق تستهای تیم Chrome که در مستندات Fetch Priority API روی web.dev منتشر شده، افزودن fetchpriority="high" به تصویر LCP در یک نمونه واقعی زمان LCP را از ۲٫۶ ثانیه به ۱٫۹ ثانیه کاهش داد، بهبود ۲۷٪ فقط با یک ویژگی HTML.
من در آخرین پروژهای که این تغییر را روی صفحه فرود یک فروشگاه اعمال کردم، حدود ۳۰۰ میلیثانیه بهبود LCP دیدم، و این تنها با اضافه کردن یک ویژگی به تگ <img> اصلی بود. مسئله ریشهای این است: مرورگرها بهطور پیشفرض تصاویر را با اولویت پایین شروع میکنند و تنها پس از پارس شدن CSS و محاسبه چیدمان میفهمند کدام تصویر در viewport اولیه قرار دارد. آن زمان معمولاً چند صد میلیثانیه از دست رفته و CSS، فونتها و اسکریپتها بخش زیادی از پهنای باند را مصرف کردهاند. fetchpriority="high" این تأخیر را حذف میکند.
<!-- درست: فقط یک تصویر LCP در صفحه -->
<img
src="/img/hero.avif"
alt="بنر اصلی خدمات"
width="1600"
height="900"
fetchpriority="high">
<!-- اگر LCP یک تصویر پسزمینه CSS است، از preload استفاده کنید -->
<link
rel="preload"
as="image"
href="/img/hero-bg.avif"
fetchpriority="high"
imagesrcset="/img/hero-bg-800.avif 800w, /img/hero-bg-1600.avif 1600w"
imagesizes="100vw">
پشتیبانی مرورگر و محدودیتها
در ۲۰۲۶ همه مرورگرهای مدرن (Chrome ۱۰۲+، Edge ۱۰۲+، Safari ۱۷٫۲+ و Firefox ۱۳۲+) از fetchpriority پشتیبانی میکنند و بر اساس گزارش مستندات MDN درباره fetchpriority، مرورگرهایی که آن را نمیشناسند بهسادگی نادیده میگیرند، پس هیچ ریسکی برای عرضه در محیط production ندارد.
Lazy Loading و اشتباه رایجی که LCP شما را نابود میکند
ویژگی بومی loading="lazy" به مرورگر میگوید بارگذاری تصویر را تا زمانی که به viewport نزدیک شود به تأخیر بیندازد. این یعنی برای صفحهای با ۴۰ تصویر که فقط ۳ تای اول در ابتدا دیده میشوند، ۳۷ درخواست تصویر صرفهجویی میشود. الگوی درست:
اما یک اشتباه رایج وجود دارد که سالانه هزاران سایت را به Core Web Vitals مردود میکند: قرار دادن loading="lazy" روی تصویر LCP. صادقانه بگویم، من این اشتباه را روی چندین سایت هنگام آدیت دیدهام؛ تیم فرانتاند بدون فکر loading="lazy" را روی همه تصاویر گذاشته و بههمین دلیل امتیاز LCP سایت روی موبایل قرمز است. وقتی تصویر LCP lazy شود، مرورگر تا محاسبه چیدمان صبر میکند، بعد شروع به دانلود میکند، دقیقاً برعکس چیزی که ما میخواهیم. طبق تحلیلهای راهنمای رفع مشکل LCP تصاویر در بلاگ MDN، این خطا معمولاً LCP را ۵۰۰ تا ۱۵۰۰ میلیثانیه بدتر میکند.
eager یا lazy یا auto؟
fetchpriority="high" + بدون loading: برای تصویر LCP.
loading="lazy": برای هر تصویری که خارج از viewport اولیه قرار دارد (لیست کارتها، تصاویر پایینتر مقاله، فوتر).
بدون هیچکدام: برای تصاویر کوچک بالای صفحه که LCP نیستند (لوگو، آواتار). مقدار پیشفرض auto کافی است.
جلوگیری از Layout Shift با width و height صریح
قبل از اینکه یک تصویر بارگذاری شود، مرورگر نمیداند چقدر فضا برای آن رزرو کند. اگر ابعاد صریح نداشته باشد، وقتی تصویر میرسد، محتوای زیر آن «هل داده» میشود، و همین همان چیزی است که Cumulative Layout Shift (CLS) اندازه میگیرد. راهحل ساده است: همیشه width و height را در HTML مشخص کنید، حتی اگر با CSS تصویر را responsive میکنید.
<!-- درست: مرورگر پیش از بارگذاری نسبت 16/9 را میداند -->
<img src="/img/card.avif" alt="..." width="1600" height="900" style="width:100%;height:auto">
<!-- در CSS برای responsive نگه داشتن نسبت -->
img { max-width: 100%; height: auto; aspect-ratio: attr(width) / attr(height); }
ویژگیهای width و height در HTML عملاً «نسبت ابعاد» را به مرورگر میگویند، نه اندازه پیکسلی نهایی. حتی اگر تصویر با CSS به ۵۰٪ عرض viewport برسد، مرورگر با استفاده از این نسبت فضای درست را از پیش رزرو میکند و CLS صفر میشود.
پسزمینههای CSS چه میشوند؟
تصاویر پسزمینه CSS (background-image) توسط مرورگر با تأخیر بارگذاری میشوند و اسکنر preload آنها را نمیبیند. اگر تصویر پسزمینه، LCP صفحه است، از <link rel="preload" as="image"> با fetchpriority="high" استفاده کنید یا بهتر، آن را به <img> واقعی با ابعاد صریح تبدیل کنید و از CSS برای موقعیتدهی استفاده کنید.
تنظیمات کیفیت فشردهسازی و ابزارهای خودکار
یک ضربهی بزرگی که در پروژههای واقعی میبینیم این است: تیم AVIF/WebP فعال میکند اما با کیفیت ۹۵ اکسپورت میکند و از خودش میپرسد چرا کاهش اندازه فقط ۱۰٪ است. کیفیتهای واقعی که در ۲۰۲۶ استفاده میشوند:
AVIF: کیفیت ۶۰ تا ۷۰ در بیشتر عکسها معادل بصری JPEG ۸۵ است.
WebP: کیفیت ۷۵ تا ۸۵ برای عکسها؛ برای گرافیک با متن، حالت lossless را امتحان کنید.
JPEG: کیفیت ۸۰ تا ۸۵ با روش mozjpeg برای فشردهسازی بهتر از libjpeg پیشفرض.
ابزارها و پایپلاین CI/CD
پیادهسازی دستی این استراتژی برای صدها تصویر ممکن نیست. ابزارهای رایج در ۲۰۲۶:
sharp (Node.js): استاندارد صنعت برای تولید انبوه AVIF/WebP در Next.js، Astro و Sveltekit. مستندات کامل روی sharp.pixelplumbing.com در دسترس است.
Squoosh CLI: ابزار مبتنی بر MozJPEG، AVIF و WebP از تیم Chrome برای CI.
ImageOptim / ImageMagick: برای بهینهسازی تکتصویر و متادیتا.
@vite/plugin-image-optimizer و astro:assets: بهینهسازی build-time در فریمورکهای مدرن.
در اینجا یک نمونه اسکریپت با sharp که یک تصویر منبع را به سه فرمت و چهار عرض تبدیل میکند:
// build-images.mjs
import sharp from "sharp";
import { readdir } from "node:fs/promises";
import path from "node:path";
const WIDTHS = [400, 800, 1200, 1800];
const SRC = "./src/images";
const OUT = "./public/img";
async function process(file) {
const base = path.parse(file).name;
const input = sharp(path.join(SRC, file));
for (const w of WIDTHS) {
const resized = input.clone().resize({ width: w });
await resized.avif({ quality: 65, effort: 6 })
.toFile(`${OUT}/${base}-${w}.avif`);
await resized.webp({ quality: 80 })
.toFile(`${OUT}/${base}-${w}.webp`);
await resized.jpeg({ quality: 82, mozjpeg: true })
.toFile(`${OUT}/${base}-${w}.jpg`);
}
}
const files = await readdir(SRC);
await Promise.all(files.map(process));
console.log(`✔ Generated ${files.length * WIDTHS.length * 3} variants`);
اجرای این اسکریپت در مرحله pre-build همه واریانتها را تولید میکند و در deploy فقط فایلهای بهینهشده به CDN میروند.
CDN تصویر: تحویل هوشمند و on-the-fly
اگر پروژهتان محتوای متغیر (مثلاً upload کاربر) دارد، پیشتولید همه واریانتها ممکن نیست. اینجاست که Image CDNها مثل Cloudinary، Imgix، Bunny Optimizer، Cloudflare Images یا سرویسهای integrated (Vercel Image Optimization، Netlify Image CDN) وارد میشوند. این سرویسها یک تصویر اصلی میگیرند و بر اساس URL parameter، در لحظه AVIF/WebP، اندازهبندی و کش را انجام میدهند.
یک نکته جانبی: در راهنمای بهینهسازی باندل جاوااسکریپت اشاره کردیم که کاهش حجم JS باعث آزاد شدن پهنای باند برای تصاویر میشود. اگر تصاویر شما هم از edge (نزدیک به کاربر) سرو شوند، هم LCP بهتر میشود هم TTFB. Cloudflare و Fastly در ۲۰۲۶ هر دو Image Optimization در PoPهای edge خود دارند.
نکات SEO و دسترسپذیری
یک تصویر بهینهشده باید همچنان قابل کشف و قابل استفاده باشد:
Alt توصیفی برای تصاویر معنیدار، alt="" برای تصاویر تزیینی.
نام فایل معنیدار (red-nike-shoe.avif نه IMG_1023.avif).
Structured Data (schema.org ImageObject) برای صفحات محصول.
Sitemap.xml اختصاصی تصاویر یا استفاده از <image:image> در sitemap اصلی.
اندازهگیری و اعتبارسنجی
بعد از اعمال تغییرات، این ابزارها را برای اعتبارسنجی اجرا کنید:
PageSpeed Insights و Lighthouse: بخش Opportunities دقیقاً میگوید کدام تصویر میتواند بهتر شود.
DevTools → Network → Priority column: اطمینان حاصل کنید که تصویر LCP شما «Highest» یا «High» است.
DevTools → Performance: در ضبط، نشانگر LCP باید روی تصویر مورد نظر شما بیفتد.
CrUX (Chrome UX Report) و Search Console → Core Web Vitals: داده میدانی واقعی از کاربران.
خلاصه اینکه، بهینهسازی تصاویر یک کار «انجام و فراموش» نیست. هر بار که تیم محتوا یک تصویر جدید upload میکند، این پایپلاین باید آن را از AVIF بگذراند، srcset تولید کند و ابعاد صریح را تزریق کند. اگر این کار خودکار باشد، سرعت سایت شما پایدار میماند حتی وقتی محتوای زیادی اضافه میشود.
پرسشهای متداول
آیا AVIF واقعاً بهتر از WebP است؟
بله، در فشردهسازی. AVIF در همان کیفیت بصری تقریباً ۲۰ تا ۲۵ درصد کوچکتر از WebP است و از HDR و 10/12-bit پشتیبانی میکند. اما WebP سرعت decode بالاتری در CPU دارد و پشتیبانی مرورگر گستردهتری (۹۶٫۴٪ در مقابل ۹۴٫۹٪). راهحل عملی: هر دو را با <picture> ارائه دهید تا مرورگر بهترین را انتخاب کند.
آیا میتوانم loading="lazy" را روی تصویر اصلی هیرو بگذارم؟
خیر، هرگز. تصویر هیرو معمولاً همان عنصر LCP است. lazy کردن آن به معنی به تأخیر انداختن مهمترین معیار Core Web Vitals است و طبق تستهای میدانی LCP را ۵۰۰ تا ۱۵۰۰ میلیثانیه بدتر میکند. تصویر هیرو باید eager بارگذاری شود، ترجیحاً با fetchpriority="high".
اگر برای تصویر width و height نگذارم چه اتفاقی میافتد؟
مرورگر قبل از بارگذاری، ارتفاع تصویر را ۰ فرض میکند و برای آن فضایی رزرو نمیکند. وقتی تصویر میرسد، محتوای زیر آن هل داده میشود و امتیاز Cumulative Layout Shift (CLS) شما بالا میرود. حتی برای تصاویر responsive، همیشه ابعاد اصلی را در HTML مشخص کنید و در CSS از width:100%;height:auto استفاده کنید.
بهترین کیفیت فشردهسازی AVIF چقدر است؟
برای بیشتر عکسهای محتوایی، کیفیت ۶۰ تا ۷۰ در AVIF از نظر بصری معادل JPEG کیفیت ۸۵ است اما فایل تا ۵۰٪ کوچکتر میشود. برای تصاویر با متن یا گرافیک تیز، کیفیت ۷۵ توصیه میشود. با ابزارهایی مثل Squoosh کیفیت را روی چند تصویر نمونه تست کنید تا نقطه شیرین پروژهتان را پیدا کنید.
آیا نیاز به Image CDN دارم یا فقط با sharp و CI کار میشود؟
اگر تعداد تصاویر شما مشخص و استاتیک است، pre-build با sharp کاملاً کافی است و ارزانترین راه است. اگر کاربران تصویر upload میکنند، محتوا زیاد تغییر میکند، یا نیاز به transform on-the-fly دارید (مثلاً کراپ چهره یا watermark)، Image CDN منطقیتر است. پروژههای ترکیبی میتوانند assets استاتیک را pre-build کنند و محتوای پویا را از CDN بگذرانند.
یاد بگیرید چطور با Tree Shaking، Code Splitting و React Server Components، باندل JavaScript را تا ۷۰٪ کاهش دهید و Core Web Vitals سایت را بهبود ببخشید.
راهنمای جامع بهینهسازی CLS در ۲۰۲۶ — از تعیین ابعاد تصاویر و فونت تا CSS Containment، bfcache و View Transitions API. آخرین بخش مجموعه Core Web Vitals.
راهنمای جامع بهینهسازی LCP (Largest Contentful Paint) در سال ۲۰۲۶. از آناتومی چهار زیرمجموعه LCP و اولویتبندی بارگذاری با fetchpriority تا فرمتهای مدرن تصویر (AVIF/WebP)، Responsive Images، Critical CSS، Early Hints و Streaming SSR.