تکنیک های Responsive کردن تصاویر

12 شهریور 1398
responsive-image

تکنیک های responsive کردن تصاویر

امروزه تعداد زیادی از توسعه دهندگان از یک تصویر استفاده و آن را با استفاده از CSS واکنش گرا (responsive) می کنند و سپس به تمامی دستگاه ها (موبایل، کامپیوتر و...) ارسال می نمایند اما باید بدانید که تکنیک های زیادی برای واکنش گرا کردن تصاویر وجود دارد. شما می توانید به جای ارسال یک تصویر به تمامی دستگاه ها، چندین نسخه از یک تصویر را داشته باشید و هر کدام را به دستگاه های خاصی ارسال کنید. بر اساس برخی از تحقیقات انجام شده، حدود 51 درصد از حجم سایت ها (و حتی بیشتر) از تصاویر تشکیل شده است و داشتن چندین نسخه از یک تصویر (به طور مثال تصاویر کوچک تر برای موبایل) می تواند حجم آن ها را شدیدا کاهش دهد. attribute های srcset و sizes و media با ارائه ی اطلاعات بیشتر به مرورگر، تگ های <img> و <source> را توسعه می دهند. بگذارید دقیق تر توضیح بدهم:

srcset به ما اجازه می دهد که مسیر تصاویر در سرور را مشخص کنیم و در عناصر <img> و <source> استفاده می شود. sizes و media نیز تقریبا یکی هستند چراکه هر دو سایز صفحه ی کاربر را مشخص می کنند. تفاوتشان در این است که sizes اجازه میدهد اندازه ی تصویر به صورت مستقل و یا به نسبت اندازه ی صفحه ی کاربر تعریف شود. ما می توانیم از sizes در عناصر <img> و <source> استفاده کنیم اما media تنها در <source> قابل استفاده است. در تمامی این حالت ها <source> باید فرزند مستقیم <picture> باشد.

مشکل استفاده از تگ img

همانطور که می دانید یک تصویر عادی در HTML به صورت زیر تعریف می شود:

<img src="/img/blog/responsive-images.png">

در واقع src به مرورگر می گوید که کجا به دنبال تصویر بگردد. شما می توانید با استفاده از attribute های width و height، عرض و طول تصویر را تعیین کنید اما این اندازه پویا نخواهد بود بنابراین در صفحات کوچک تر با تصاویر بزرگتری برخورد خواهید کرد. به همین دلیل است که می بینید اکثر برنامه های وب برای استایل دهی تصاویر از کلاس ها استفاده می کنند:

<img src="/img/blog/responsive-images.png" alt="responsive images" class="img-fluid rounded">

مشکل اینجاست که استفاده از تگ <img> تنها یک سورس را برای تصویر ما مشخص خواهد کرد. به عبارت دیگر فارغ از اینکه کاربر با چه دستگاهی یا چه سایز صفحه ای وارد سایت ما شده است، ما تنها یک تصویر را به او ارائه می دهیم. با اینکه با استفاده از CSS می توان این تصویر را واکنش گرا کرد (مثلا کلاس img-fluid بالا) اما هنوز هم تصویر بسیار بزرگی را برای گوشی موبایل ارسال کرده و سپس با کدها آن را تغییر می دهیم که به نوعی دوباره کاری محسوب می شود و ترافیک سرور ما را بدون دلیل شلوغ تر خواهد کرد. معمولا ارسال یک تصویر بزرگ به تمامی دستگاه ها باعث کاهش سرعت، افزایش حجم صفحه و هدر دادن پهنای باند می شود.

کار با srcset

ما می توانیم از attribute ای به نام srcset در تگ های img و source استفاده کنیم؛ برای کار با آن باید اندازه ی صفحه را بعد از نام تصویر اضافه کنیم (به طور مثال 730w یا 350w و ...) تا مرورگر با توجه به اندازه ی صفحه ی کاربر تصویر مورد نظر را بارگذاری کند:

<img srcset="responsive-images-lg.png 730w,
             responsive-images-md.png 610w,
             responsive-images-sm.png 350w"
     src="reponsive-images.png"
     alt="responsive images">
<picture>
    <source srcset="/img/blog/responsive-images-lg.png 730w">
    <source srcset="/img/blog/responsive-images-md.png 610w">
    <source srcset="/img/blog/responsive-images-sm.png 350w">
    <img src="reponsive-images.png" alt="responsive images" class="img-fluid rounded">
</picture>

مشکل این روش این است که ما برای ارسال تصاویر، فقط و فقط بر اساس سایز صفحه ی کاربر تصمیم گیری می کنیم. اینجاست که size به کمک ما می آید...

کار با sizes

attribute دیگری به نام sizes وجود دارد که به مروگر می گوید اندازه ی دقیق هر تصویر به نسبت اندازه ی viewport چقدر باشد. sizes این کار را از طریق media condition ها انجام می دهد که بسیار شبیه به media query ها هستند. برای مثال ما می توانیم از sizes در یک srcset استفاده کنیم:

<img sizes="(min-width: 1200px) 730w,
            (max-width: 1199px) 610w,
            (max-width: 380px) 350w"
     srcset="responsive-images-lg.png 730w,
             responsive-images-md.png 610w,
             responsive-images-sm.png 350w"
     src="reponsive-images.png"
     alt="responsive images">
<picture>
    <source sizes="(min-width: 1200px) 730w" srcset="/img/blog/responsive-images-lg.png 730w">
    <source sizes="(max-width: 1199px) 610w" srcset="/img/blog/responsive-images-md.png 610w">
    <source sizes="(max-width: 380px) 350w" srcset="/img/blog/responsive-images-sm.png 350w">
    <img src="reponsive-images.png" alt="responsive images" class="img-fluid rounded">
</picture>

sizes در هنگام کار با عنصر img بسیار کاربردی و مفید عمل می کند اما اگر از <source> استفاده می کنید بهتر است به سراغ media بروید.

کار با media

attribute ای به نام media نیز وجود دارد که اجازه می دهد چیزی به نام media condition را تعریف کنیم. اگر <source> فرزند مستقیم <picture> باشد می توانیم از media استفاده کنیم. همچنین اگر شرط تعریف شده توسط media صحیح باشد از <source> مربوط به آن شرط استفاده می شود و در غیر این صورت آن <source> نادیده گرفته خواهد شد. مثال:

<picture>
    <source media="(min-width: 1200px)" srcset="/img/blog/responsive-images-lg.png">
    <source media="(max-width: 1199px)" srcset="/img/blog/responsive-images-md.png">
    <source media="(max-width: 380px)" srcset="/img/blog/responsive-images-sm.png">
    <img src="reponsive-images.png" alt="responsive images" class="img-fluid rounded">
</picture>

جدا از اینکه می توانیم بر اساس سایز viewport تصاویر مختلفی را ارسال کنیم، باید بدانید که می توانیم بر اساس pixel density (تراکم پیکسلی) صفحه ی کاربر نیز تصاویر مختلفی را انتخاب و ارسال کنیم!

تراکم پیکسلی نمایشگر و density descriptor

برخی از صفحات نمایش (مانند صفحات retina 4k) دارای تراکم پیکسلی بسیار بالایی می باشند که در نحوه ی نمایش تصاویر ما موثر خواهند بود. density descriptor ها روش بسیار مناسبی برای نمایش تصاویر در این صفحات متراکم هستند و ما با استفاده از دستورات 1x و 2x و 3x آن ها را تعریف می کنیم. این دستورات به ما اجازه می دهند که بدون دستکاری ابعاد تصویر، نسخه ای چند برابر بزرگ تر از آن را برای کاربر نمایش دهیم. به مثال زیر توجه کنید:

<img sizes="(min-width: 1200px) 730w,
            (max-width: 1199px) 610w,
            (max-width: 380px) 350w"
     srcset="responsive-images-lg.png 730w 1x,
             responsive-images-lg@2x.png 730w 2x,
             responsive-images-md.png 610w 1x,
             responsive-images-md@2x.png 610w 2x,
             responsive-images-sm.png 350w 1x,
             responsive-images-sm@2x.png 350w 2x"
     src="reponsive-images.png"
     alt="responsive images">
<picture>
    <source media="(min-width: 1200px)" srcset="/img/blog/responsive-images-lg.png 1x, /img/blog/responsive-images-lg@2x.png 2x">
    <source media="(max-width: 1199px)" srcset="/img/blog/responsive-images-md.png 1x, /img/blog/responsive-images-md@2x.png 2x">
    <source media="(max-width: 380px)" srcset="/img/blog/responsive-images-sm.png 1x, /img/blog/responsive-images-sm@2x.png 2x">
    <img src="reponsive-images.png" alt="responsive images" class="img-fluid rounded">
</picture>

اگر از این descriptor ها استفاده می کنید دیگر نیازی به استفاده از sizes یا media نخواهید داشت اما زمانی که از 2x یا 3x استفاده می کنیم واقعا باید تصاویر 2 برابر یا 3 برابر بزرگتر داشته باشیم.

ترکیب این تکنیک ها با فرمت webP

قبلا در مقاله ای با فرمت WebP آشنا شده بودیم و می دانیم که تصاویر با این فرمت معمولا حجم کمتری نسبت به تصاویر png یا jpeg دارند (بدون اینکه کیفیت کمتری داشته باشند). بنابراین اگر تکنیک های معرفی شده در این مقاله را با آن ها ترکیب کنیم وب سایت سریع تری خواهیم داشت:

<picture>
    <source type="image/webp" media="(min-width: 1200px)" srcset="/img/blog/responsive-images-lg.webp 1x, /img/blog/responsive-images-lg@2x.webp 2x">
    <source type="image/webp" media="(max-width: 1199px)" srcset="/img/blog/responsive-images-md.webp 1x, /img/blog/responsive-images-md@2x.webp 2x">
    <source type="image/webp" media="(max-width: 380px)" srcset="/img/blog/responsive-images-sm.webp 1x, /img/blog/responsive-images-sm@2x.webp 2x">
    <source type="image/png" media="(min-width: 1200px)" srcset="/img/blog/responsive-images-lg.png 1x, /img/blog/responsive-images-lg@2x.png 2x">
    <source type="image/png" media="(max-width: 1199px)" srcset="/img/blog/responsive-images-md.png 1x, /img/blog/responsive-images-md@2x.png 2x">
    <source type="image/png" media="(max-width: 380px)" srcset="/img/blog/responsive-images-sm.png 1x, /img/blog/responsive-images-sm@2x.png 2x">
    <img src="reponsive-images.png" alt="responsive images" class="img-fluid rounded">
</picture>

پشتیبانی مرورگرها

اکثر مرورگرهای مدرن و امروزی از srcset پشتیبانی می کنند (به استثنای opera mini و internet explorer)، حتی Edge نیز از srcset پشتیبانی می کند اما اگر مرورگر از این ویژگی نیز پشتیبانی نکند هیچ جای نگرانی نیست چرا که به صورت خودکار از تصویر پیش فرض استفاده می کند:

  • اگر از <img> استفاده می کنید، تصویر پیش فرض مقدار src خواهد بود.
  • اگر از <picture> استفاده می کنید، تصویر پیش فرض مقدار تعریف شده در <img> خواهد بود.

بنابراین هیچ عیبی برای استفاده از آن وجود ندارد.

چرا به خودمان زحمت بدهیم؟

دلیل اصلی استفاده از تصاویر واکنش گرا به شیوه های مطرح شده کاهش حجم تصاویر در سایت است که در نهایت به افزایش سرعت سایت منجر می شود. به نمونه ی زیر نگاه کنید:

نسخه های مختلف یک تصویر واکنش گرا - responsive کردن تصاویر
نسخه های مختلف یک تصویر واکنش گرا

سایز اصلی تصویر 30 کیلوبایت است اما برای گوشی های موبایل نسخه ی کوچک تر به حجم 10 کیلوبایت ارسال می شود که یعنی 65 درصد کاهش حجم! این فقط یک نمونه است، چنین حالتی را در یک سایت بزرگ و پر از تصویر فرض کنید!

امیدوارم مقاله responsive کردن تصاویر، درک بهتری نسبت به تصاویر واکشن گرا به شما داده باشد.

نویسنده شوید
دیدگاه‌های شما (2 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

usEr
22 خرداد 1400
ممنون از توضیحات مفیدتون موفق باشید

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

mobin ghaemi
11 دی 1399
عالی

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.