الخطوات
-
1
أضف loading="lazy" للصور خارج مرأى الشاشة
هذا هو الحل الأبسط والأكثر فاعلية. أي صورة غير مرئية عند التحميل الأولي يجب أن تحمل
loading="lazy". مدعوم في جميع المتصفحات الحديثة. لا JavaScript، لا مكتبات — خاصية واحدة فقط.html<!-- صورة منتج أسفل الطيّة: حمّلها بشكل كسول --> <img src="product-photo.jpg" alt="مكتب خشبي بإعداد نظيف" width="800" height="600" loading="lazy" > -
2
لا تُحمّل صور أعلى الصفحة بشكل كسول
صور الـ hero، والشعار، وكل ما هو مرئي دون تمرير يجب ألا يُحمَّل بشكل كسول. التحميل الكسول يؤخر اكتشاف المتصفح للصورة ويضر مباشرة بمقياس Largest Contentful Paint (LCP). لأهم صورة فوق الطيّة، أضف
fetchpriority="high"أيضاً.html<!-- Hero: eager (الافتراضي) + أولوية عالية --> <img src="hero.jpg" alt="لقطة hero للمنتج" width="1200" height="675" fetchpriority="high" > <!-- أول صورة مرئية في قائمة: eager، لا حاجة لـ fetchpriority --> <img src="first-card.jpg" alt="أول بطاقة" width="400" height="300" > -
3
حدد العرض والارتفاع دائماً
بدون أبعاد صريحة لا يستطيع المتصفح حجز مساحة للصورة أثناء تحميلها. النتيجة هي Cumulative Layout Shift (CLS) — ينتقل المحتوى عند وصول الصورة.
widthوheightلا يفرضان حجماً بصرياً ثابتاً؛ CSS لا تزال تتحكم في ذلك. إنها فقط تعطي المتصفح نسبة الأبعاد التي يحتاجها لحجز المساحة مسبقاً.html<!-- خاطئ: لا أبعاد = انزياح التخطيط --> <img src="photo.jpg" alt="..." loading="lazy"> <!-- صحيح: نسبة الأبعاد محددة، لا انزياح --> <img src="photo.jpg" alt="..." width="800" height="533" loading="lazy" > -
4
استخدم srcset للصور المتجاوبة
اعرض الدقة المناسبة لكل حجم شاشة. يختار المتصفح الأنسب من قائمة
srcset. ادمج هذا معloading="lazy"— يعملان باستقلالية تامة.html<img src="photo-800.jpg" srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w" sizes="(max-width: 600px) 100vw, (max-width: 900px) 50vw, 800px" alt="صورة متجاوبة" width="800" height="533" loading="lazy" > -
5
استخدم <picture> للتبديل بين صيغ الصور
اعرض WebP للمتصفحات التي تدعمه وارجع إلى JPEG لبقيتها. يختار
<picture>أول<source>يستطيع المتصفح التعامل معه.loading="lazy"يذهب على عنصر<img>الاحتياطي — وليس على عناصر<source>.html<picture> <source type="image/webp" srcset="photo-400.webp 400w, photo-800.webp 800w" sizes="(max-width: 600px) 100vw, 800px" > <source type="image/jpeg" srcset="photo-400.jpg 400w, photo-800.jpg 800w" sizes="(max-width: 600px) 100vw, 800px" > <img src="photo-800.jpg" alt="صورة المنتج" width="800" height="533" loading="lazy" > </picture> -
6
بناء بديل IntersectionObserver
للمتصفحات التي لا تدعم
loading="lazy"(بشكل رئيسي Safari قبل iOS 15.4 وإصدارات Chrome القديمة)، استخدم IntersectionObserver. خزّن الرابط الحقيقي فيdata-srcوبادله إلىsrcعندما تدخل الصورة نطاق الرؤية.javascriptif ('loading' in HTMLImageElement.prototype) { // التحميل الكسول الأصلي مدعوم — لا شيء نفعله } else { // بديل: IntersectionObserver const images = document.querySelectorAll('img[data-src]'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (!entry.isIntersecting) return; const img = entry.target; img.src = img.dataset.src; if (img.dataset.srcset) img.srcset = img.dataset.srcset; img.removeAttribute('data-src'); observer.unobserve(img); }); }, { rootMargin: '200px' }); // حمّل 200px قبل الدخول للرؤية images.forEach(img => observer.observe(img)); } -
7
ضع رابط الصورة في data-src للصور الاحتياطية
عند تفعيل البديل، يخزّن HTML للصور الكسولة الرابط في
data-srcبدلاً منsrc. استخدم placeholder شفاف 1×1 فيsrcحتى يظل العنصر صالحاً. المتصفحات الحديثة تستخدم خاصيةloadingولا تقرأdata-srcأبداً.html<!-- يعمل مع التحميل الكسول الأصلي والبديل JS --> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-src="actual-photo.jpg" data-srcset="actual-photo-400.jpg 400w, actual-photo-800.jpg 800w" alt="صورة المنتج" width="800" height="533" loading="lazy" >
نصائح ومحاذير
- أول صورة في قائمة متكررة (بطاقات، منتجات) تكون غالباً فوق الطيّة على الشاشات الكبيرة — تحقق قبل إضافة التحميل الكسول.
- <code>loading="lazy"</code> يعمل أيضاً على عناصر <code><iframe></code> وليس فقط الصور. مفيد لتأجيل تحميل الخرائط أو مقاطع الفيديو المضمّنة.
- استخدم <code>rootMargin</code> بقيمة 200–400px في IntersectionObserver حتى تبدأ الصور بالتحميل قبل وصولها لنطاق الرؤية، متجنباً ظهورها الفجائي المرئي.
- شغّل Google Lighthouse أو WebPageTest بعد إضافة التحميل الكسول. تحقق أن LCP لم يتدهور — خطأ شائع هو تحميل صورة LCP بشكل كسول.
- لصور الخلفية في CSS (وليس <code><img></code>)، لا يوجد تحميل كسول أصلي. استخدم IntersectionObserver لإضافة/إزالة class يضبط <code>background-image</code>.
خاتمة
في معظم المشاريع، إضافة loading="lazy" لجميع الصور أسفل الطيّة وتحديد width/height لكل صورة يكفي لتحقيق تحسن ملموس في الأداء. يستحق إضافة بديل IntersectionObserver إذا كنت بحاجة لدعم المتصفحات القديمة، لكن الخاصية الأصلية تغطي الغالبية العظمى من حركة المرور الحقيقية. القاعدة الأهم: لا تُحمّل صورة LCP بشكل كسول أبداً.