بارگذاری تنبل تصاویر
در یک صفحه وب میتوان تصاویر را به شیوههای مختلفی نمایش داد، تصاویر در HTML بهصورت عناصر یا تصاویر پسزمینه CSS قرار دارند. در این مقاله میآموزیم که چگونه هر دو نوع تصویر را بهصورت lazy loading بارگذاری کنیم.
آنچه در این مقاله میخوانیم
تصاویر درون خطی(Inline)
رایجترین گزینههای بارگذاری تنبل، تصاویری هستند که در عناصر <img> استفاده میشوند. برای تصاویر درون خطی(Inline) سه گزینه برای بارگذاری تنبل داریم که گاهی ممکن است به صورت ترکیبی برای سازگاری در بین مرورگرها مختلف استفاده شود:
استفاده از بارگذاری تنبل تصاویر در سطح مرورگر
کروم و فایرفاکس هر دو از بارگذاری تنبل تصاویر با ویژگی loading
پشتیبانی میکنند. این ویژگی را می توان به عناصر <img>
و همچنین به عناصر <iframe>
اضافه کرد. خاصیت lazy
به مرورگر میگوید که اگر تصویر در پنجره دید کاربر(viewport) است، فوراً آن را بارگیری کند و برای سایر تصاویر تا زمانی که کاربر به نزدیک آنها نرسیده است آنها را بارگیری نکند.
مقاله : بارگذاری تنبل تصاویر در سطح مرورگر
توجه:
<iframe loading="lazy">
در حال حاضر استاندارد نیست، در حالی که در Chromium پیادهسازی شدهاست، هنوز توسط ارگانهای مهم استاندارد سازی تثبیت نشده است. پیشنهاد میکنیم تا زمان تثبیت و استاندارد شدن از بارگذاری تنبل iframes ها اجتناب کنید.
برای دیدن جزئیات پشتیبانی مرورگرها از بارگذاری تنبل تصاویر، به قسمت browser compatibility مرجع MDN مراجعه کنید. اگر مرورگر از بارگذاری تنبل پشتیبانی نکند، این ویژگی نادیده گرفته میشود و طبق معمول، تصاویر بلافاصله بارگیری میشوند.
برای اکثر وبسایتها، افزودن این ویژگی به تصاویر درون خطی باعث بهبود سرعت و عملکرد سایت میشود و کاربران را از هزینه و زمان بارگذاری تصاویری که ممکن است هرگز روی آنها اسکرول نکنند، نجات میدهد. اگر تعداد زیادی عکس دارید و میخواهید مطمئن شوید که همه کاربران (حتی آنهایی که مرورگرشان از image lazy loading پشتیبانی نمیکند) به خوبی از تصاویر بهره ببرند باید از ترکیب این روشها استفاده کنید.
بارگذاری تنبل تصاویر با استفاده از Intersection Observer
برای تکمیل بارگذاری تنبل عناصر <img>
، از جاوا اسکریپت استفاده می کنیم تا بررسی کنیم که آیا آنها در viewport هستند یا خیر. در صورت وجود، ویژگیهای src
(و گاهی اوقات srcset
) آنها با URLهای محتوای تصویر مورد نظر پر میشوند.
اگر قبلاً کدهایی با بارگذاری تنبل نوشتهاید، ممکن است کار خود را با استفاده از کنترلکنندههای رویداد مانند scroll
یا تغییر اندازه (resize
) انجام داده باشید. در حالی که این رویکرد در بین مرورگرها سازگارترین است، مرورگرهای مدرن روشی کارآمدتر و کارآمدتر برای انجام کار بررسی قابلیت مشاهده عناصر از طریق the Intersection Observer API. ارائه میدهند.
Intersection Observer در همه مرورگرها، به ویژه IE11 و پایینتر، پشتیبانی نمیشود. اگر سازگاری در بین مرورگرها بسیار مهم است، حتماً بخش بعدی را بخوانید، که به شما نشان میدهد چگونه با استفاده از کنترلکنندههای رویداد با سرعت کمتر (اما سازگارتر!) تصاویر را بارگذاری کنید.
پشتیبانی از Intersection Observer
دسکتاپ
کروم | فایرفاکس | IE | Edge | Safari |
---|---|---|---|---|
58 | 55 | No | 16 | 12.1 |
موبایل و تبلت
کروم اندروید | فایرفاکس اندروید | مرورگر اندروید | سافاری ای او اس |
---|---|---|---|
98 | 96 | 98 | 12.2-12.5 |
استفاده و خواندن از Intersection Observer نسبت به نوشتن کد سفارشی با تکیه بر کنترلکنندههای مختلف رویداد آسانتر است، زیرا شما فقط باید یک ناظر را برای تماشای عناصر به جای نوشتن کد تشخیص دید عنصر خستهکننده ثبت کنید. تنها کاری که باید انجام دهید این است که تصمیم بگیرید وقتی یک عنصر قابل مشاهده است چه کاری انجام دهید. بیایید این الگوی نشانه گذاری اولیه را برای عناصر <img>
شما که با تنبلی بارگذاری شدهاند امتحان کنیم.
<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="I'm an image!">
در مورد کد html بالا سه نکته مهم وجود دارد که باید به آنها توجه کنیم:
حال با استفاده از Intersection Observer در جاوا اسکریپت تصویر html بالا را به صورت تنبل بارگذاری میکنیم:
document.addEventListener("DOMContentLoaded", function() { var lazyImages = [].slice.call(document.querySelectorAll("img.lazy")); if ("IntersectionObserver" in window) { let lazyImageObserver = new IntersectionObserver(function(entries, observer) { entries.forEach(function(entry) { if (entry.isIntersecting) { let lazyImage = entry.target; lazyImage.src = lazyImage.dataset.src; lazyImage.srcset = lazyImage.dataset.srcset; lazyImage.classList.remove("lazy"); lazyImageObserver.unobserve(lazyImage); } }); }); lazyImages.forEach(function(lazyImage) { lazyImageObserver.observe(lazyImage); }); } else { // Possibly fall back to event handlers here } });
در رویداد DOMContentLoaded صفحه ، برای تمامی تصاویری که کلاس آنها lazy است، یک ناظر جدید ایجاد میکنیم تا زمانی که عناصر img.lazy وارد viewport کاربر می شوند، تصویر اصلی جایگزین تصویر مکان نگه دار شود.
Intersection Observer در تمام مرورگرهای مدرن پشتیبانی میشود. بنابراین استفاده از آن تضمین میکند که بارگذاری تنبل برای اکثر بازدیدکنندگان در دسترس خواهد بود.البته این امکان در اینترنت اکسپلورر موجود نیست و اگر پشتیبانی از اینترنت اکسپلورر برای شما مهم است از این روش صرف نظر کنید.
استفاده از کنترل کننده رویداد(event handlers) برای بارگذاری تنبل تصاویر
اگر تعدادی از کاربران شما از Intersection Observer پشتیبانی نمیکنند میتوانید در کنار استفاده از Intersection Observer برای مرورگرهای مدرن، از کنترلکنندههای رویداد برای مرورگرهای قدیمی استفاده کنید. میتوانید با استفاده از رویدادهای اسکرول، تغییر اندازه و … تعیین کنید که آیا یک عنصر در viewport است یا خیر و بعد از آن اقدام به لود تصویر اصلی کنید.
document.addEventListener("DOMContentLoaded", function() { let lazyImages = [].slice.call(document.querySelectorAll("img.lazy")); let active = false; const lazyLoad = function() { if (active === false) { active = true; setTimeout(function() { lazyImages.forEach(function(lazyImage) { if ((lazyImage.getBoundingClientRect().top <= window.innerHeight && lazyImage.getBoundingClientRect().bottom >= 0) && getComputedStyle(lazyImage).display !== "none") { lazyImage.src = lazyImage.dataset.src; lazyImage.srcset = lazyImage.dataset.srcset; lazyImage.classList.remove("lazy"); lazyImages = lazyImages.filter(function(image) { return image !== lazyImage; }); if (lazyImages.length === 0) { document.removeEventListener("scroll", lazyLoad); window.removeEventListener("resize", lazyLoad); window.removeEventListener("orientationchange", lazyLoad); } } }); active = false; }, 200); } }; document.addEventListener("scroll", lazyLoad); window.addEventListener("resize", lazyLoad); window.addEventListener("orientationchange", lazyLoad); });
کد بالا تقریباً در هر مرورگری کار میکند امابه دلیل فراخوانی مکرر setTimeout
باعث مشکلاتی برای سرعت صفحه خواهد، اگر هدف ما از بارگذاری تنبل افزایش سرعت لود اولیه صفحه باشد در صفحات با تصاویر زیاد استفاده از این متد نتیجه عکس خواهد داد و فراخوانی مکرر کدها باعث کند شدن صفحه خواهد شد.
به بیان ساده: تا جایی که ممکن است از بارگذاری تنبل با Intersection Observer استفاده کنید و تنها در صورتی از کنترل کننده رویداد استفاده کنید که نیاز به سازگاری با مرورگرهای قدمی بسیار ضروری باشد.
کتابخانه هایی برای بارگذاری تنبل تصاویر
از کتابخانه های زیر میتوان برای بارگذاری تنبل تصاویر استفاده کرد.