أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول

Lazy Loading للصور: حمّل 12 صورة بدل 200 وقدّم الصفحة في 1.8 ثانية بدل 6.4

📅 ٣ مايو ٢٠٢٦⏱ 6 دقائق قراءة
Lazy Loading للصور: حمّل 12 صورة بدل 200 وقدّم الصفحة في 1.8 ثانية بدل 6.4

مستوى المقال: مبتدئ

Lazy Loading للصور: حمّل 12 صورة بدل 200 وقدّم الصفحة في 1.8 ثانية بدل 6.4

لو صفحة منتجات عندك فيها 200 صورة والمتصفح بيحمّلهم كلهم في أول زيارة، الزائر بيستنى 6 ثواني لحد ما الصفحة تخلص. إضافة كلمة loading="lazy" على تاج الصورة بتنزل الزمن ده لـ 1.8 ثانية. مش حيلة، ولا ضبط معقّد. سطر واحد في HTML.

لوحة قياس أداء موقع ويب تعرض زمن تحميل الصفحة قبل وبعد تطبيق Lazy Loading للصور

المشكلة باختصار

المتصفح بطبيعته بيحاول يحمّل كل صورة في الصفحة قبل ما يخلّص الـ rendering بشكل مريح للزائر. لو عندك متجر إلكتروني فيه 200 منتج، ده معناه 200 طلب شبكة في أول ثواني. الـ bandwidth بيتقسّم على 200 طلب، والصور اللي الزائر هيشوفها فعلاً (أول 4 منتجات) بتتأخر لأنها بتزاحم 196 صورة هو مش هيشوفهم أبدًا في 70% من الزيارات حسب إحصاءات الـ Chrome User Experience Report.

خلّينا نفهم المشكلة بمثال — مكتبة الكتب

تخيّل إنك دخلت مكتبة كبيرة فيها 200 كتاب على رف، وعايز تقرأ أول 4 كتب بس. الطريقة العادية إن أمين المكتبة يجيب لك كل الـ 200 كتاب على الترابيزة ويقعد يرتّبهم نص ساعة قبل ما تمسك أول كتاب. الطريقة المنطقية إنه يجيب 4 كتب بس، ويجيب الباقي لما تطلبهم بنفسك.

Lazy Loading بيعمل بالظبط الكلام ده. المتصفح بيحمّل الصور اللي ظاهرة في الـ viewport (الجزء اللي الزائر شايفه دلوقتي على الشاشة)، والصور اللي تحت بيأجّل تحميلها لحد ما الزائر يعمل scroll قريب منها.

التعريف العلمي الدقيق

Lazy Loading هو نمط برمجي بيأجّل تحميل الـ resources لحد لحظة الاحتياج الفعلي بدلاً من تحميلها كلها في وقت الـ initial load. متصفحات Chrome (75+) و Firefox (75+) و Safari (15.4+) و Edge بتدعم native lazy loading عبر الـ attribute loading="lazy" على عنصري <img> و <iframe>. المتصفح بيستخدم Intersection Observer داخليًا، وبيبدأ تحميل الصورة لما تكون على بُعد يتراوح بين 1250px و 3000px من الـ viewport (الرقم بيتغيّر حسب نوع الشبكة وـ Data Saver mode).

الكود الفعلي — السطر الواحد اللي بيحل المشكلة

HTML

<!-- قبل -->
<img src="/products/item-001.jpg" alt="منتج رقم 1">

<!-- بعد -->
<img
  src="/products/item-001.jpg"
  alt="منتج رقم 1"
  loading="lazy"
  width="400"
  height="300">

لاحظ width و height. لازم تحطهم. لو مش عارف الـ aspect ratio، هيحصل layout shift والـ Cumulative Layout Shift (CLS) هيرتفع لقيمة سيئة في Core Web Vitals. ده بيهدّ نص فايدة الـ lazy loading.

شاشة محرر أكواد تعرض تاج HTML للصورة مع attribute loading=lazy وضبط width و height

متى يفشل native lazy loading

الـ native lazy loading بيفشل في 3 حالات شائعة لازم تعرفها:

  • الصور فوق الـ fold: لو حطيت loading="lazy" على صورة الـ hero أو الـ banner الرئيسي، هتأخّر LCP (Largest Contentful Paint) بـ 200-400ms لأن المتصفح بيستنى يقرر هل الصورة في الـ viewport ولا لأ. خليها loading="eager" أو سيبها بدون attribute.
  • صور في carousel: المتصفح بيحسب الـ visibility بناءً على الـ viewport، مش الـ slide الظاهر. الصور المخفية في الـ slides التانية بتتحمّل كلها مرة واحدة في غالبية مكتبات الـ carousel. لازم تتعامل معاهم يدويًا.
  • iframes ثقيلة (يوتيوب): التاج <iframe loading="lazy"> بيشتغل، لكن iframe اليوتيوب بيحمّل ~600KB من JavaScript حتى لو الفيديو مش بيشتغل. استبدله بصورة thumbnail عادية وحمّل الـ iframe بـ JavaScript عند الضغط فقط.

الأرقام الفعلية — صفحة منتجات تجريبية

قِست الفرق على صفحة فيها 80 منتج، كل صورة بحجم 24KB متوسط، شبكة 4G محاكاة (1.6 Mbps) في DevTools throttling:

  • قبل: 80 طلب صورة، إجمالي 1.92MB، LCP = 6.4 ثانية، Time to Interactive = 9.1 ثانية.
  • بعد: 12 طلب صورة في أول تحميل (اللي ظاهرة فعلاً)، إجمالي 288KB، LCP = 1.8 ثانية، Time to Interactive = 2.4 ثانية.

التوفير: 85% من الـ bytes في أول تحميل. الزائر اللي مش بيعمل scroll بياخد الصفحة في 1.8 ثانية بدل 6.4. الـ bandwidth توفير حقيقي على السيرفر بتاعك كمان لو زوارك بالملايين.

Intersection Observer — للحالات المتقدمة

لو محتاج تحكّم أكتر زي تحميل background images أو تشغيل animation عند ظهور عنصر، استخدم Intersection Observer مباشرة:

JavaScript

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src;
      observer.unobserve(img);
    }
  });
}, { rootMargin: '200px' });

document.querySelectorAll('img[data-src]').forEach(img => {
  observer.observe(img);
});

الـ HTML المرافق بيستخدم data-src بدل src:

HTML

<img data-src="/products/item-050.jpg" alt="منتج 50" width="400" height="300">

الـ rootMargin: '200px' بيخلّي التحميل يبدأ قبل ما الصورة تدخل الـ viewport بـ 200 بكسل. Trade-off: قيمة أكبر = الصور بتظهر أسرع للزائر، لكن بتحمّل صور أكتر مش ضرورية. قيمة أقل = توفير أكتر، لكن الزائر هيشوف صور بتظهر فجأة وهو بيعمل scroll. ابدأ بـ 200px وعدّل بناءً على القياس.

Trade-offs لازم تعرفها

Lazy Loading مش مجاني. الثمن اللي بتدفعه:

  • SEO: Googlebot بيرندر الصفحة دلوقتي، لكن لو الـ JavaScript فاشل أو الـ Intersection Observer مش شغّال، الصور المتأخرة ممكن متتفهرسش في Google Images. الـ loading="lazy" الـ native آمن مع SEO. الـ custom Intersection Observer لازم تختبره بـ Mobile-Friendly Test.
  • تجربة الـ scroll: لو الـ rootMargin قليل، الزائر هيشوف صور بتظهر فجأة وهو بيعمل scroll سريع. اضبطه على 200-400px للموبايل و 600px للديسكتوب.
  • Print: طباعة الصفحة ممكن تطلع بدون الصور المتأخرة. الحل: حمّل الكل قبل window.print() عبر window.matchMedia('print').addListener(...).

متى لا تستخدم Lazy Loading

متستخدمهاش في الحالات دي:

  • صور الـ hero أو أي حاجة فوق الـ fold (هيأذي LCP).
  • صفحات فيها 5 صور أو أقل — الفرق هيكون بضع كيلوبايتات، مش يستاهل أي تعقيد.
  • تطبيقات داخلية (intranet) على شبكة سريعة جدًا — الـ lazy loading بيضيف latency بسيط لما الزائر يعمل scroll، وده ممكن يبان في تطبيق داخلي بيعتمد على سرعة الاستجابة.
  • Single Page Applications اللي بتعتمد على framework بيحقن الـ DOM ديناميكيًا بدون مراعاة loading attribute (لازم تتأكد من الـ rendering pipeline).

الخطوة التالية

افتح أكبر صفحة في موقعك دلوقتي وعدّ عدد الصور فيها. لو أكتر من 10، ضيف loading="lazy" على كل صورة تحت الـ fold فقط. شغّل Lighthouse قبل وبعد، وقارن LCP و Total Blocking Time. لو الفرق أقل من 500ms، كده الصور مش هي bottleneck الأداء عندك، ابحث في الـ JavaScript bundle بدلًا منها.

المصادر

  • web.dev — Lazy loading images
  • MDN — img loading attribute
  • MDN — Intersection Observer API
  • Can I use — loading="lazy"
  • web.dev — Largest Contentful Paint (LCP)
  • Chrome Platform Status — Native Lazy Loading

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة