<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Manu Chaudhary</title>
    <description>The latest articles on DEV Community by Manu Chaudhary (@manu4543).</description>
    <link>https://dev.to/manu4543</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F519959%2F013d4936-7d54-4c3c-82c3-56fa28d13961.png</url>
      <title>DEV Community: Manu Chaudhary</title>
      <link>https://dev.to/manu4543</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/manu4543"/>
    <language>en</language>
    <item>
      <title>Extending Lighthouse for custom image and video optimization analysis</title>
      <dc:creator>Manu Chaudhary</dc:creator>
      <pubDate>Tue, 26 Nov 2024 04:57:20 +0000</pubDate>
      <link>https://dev.to/manu4543/extending-lighthouse-for-custom-image-and-video-optimization-analysis-12ao</link>
      <guid>https://dev.to/manu4543/extending-lighthouse-for-custom-image-and-video-optimization-analysis-12ao</guid>
      <description>&lt;p&gt;Optimizing website performance is critical for delivering seamless user experiences and achieving better search rankings. &lt;/p&gt;

&lt;p&gt;While tools like Google PageSpeed Insights and &lt;a href="https://github.com/GoogleChrome/lighthouse" rel="noopener noreferrer"&gt;Lighthouse&lt;/a&gt; are popular choices for performance analysis, they often fall short in addressing video content, offering only generic recommendations such as "Avoid enormous network payloads".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcks86atq7gfcaprbfkjy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcks86atq7gfcaprbfkjy.png" alt="Lighthouse generic Large network payload audit" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We faced this challenge when we wanted to develop a &lt;a href="https://imagekit.io/website-analyzer/" rel="noopener noreferrer"&gt;tool&lt;/a&gt; that could evaluate both images and videos. Specifically, we aimed to detect whether videos were encoded using next-generation codecs like VP9 or AV1.&lt;/p&gt;

&lt;p&gt;So, we extended Lighthouse by creating a custom audit—and surprisingly, the process was quite straightforward.&lt;/p&gt;

&lt;p&gt;Before diving into the details of the custom audit, let’s explore how ImageKit’s Website Performance Analyzer simplifies media performance evaluation.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Website Performance Analyzer Works
&lt;/h2&gt;

&lt;p&gt;The ImageKit &lt;a href="https://imagekit.io/website-analyzer/" rel="noopener noreferrer"&gt;Website Performance Analyzer&lt;/a&gt; is a free tool designed to evaluate both image and video content on your website. It generates detailed audit reports for both mobile and desktop versions, scoring websites based on key performance metrics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Device Emulation&lt;/strong&gt;: Simulates real-world performance by replicating both mobile (e.g., Moto G Power) and desktop environments, allowing for accurate assessment across different devices and screen sizes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Comprehensive Overall Media Audit&lt;/strong&gt;: Analyzes images and videos on your site to uncover issues such as missing size attributes, non-responsive or improperly sized media, lack of lazy loading, and the absence of next-generation formats like AVIF or WebP. Provides actionable insights to optimize media performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Video-Specific Analysis&lt;/strong&gt;: Identifies whether videos are encoded using advanced codecs like VP9 or AV1 to enhance playback efficiency, reduce bandwidth usage, and improve performance across modern browsers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Scoring&lt;/strong&gt;: Assigns detailed performance scores based on weighted factors, helping prioritize key areas for optimization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automated Monitoring with Weekly Alerts&lt;/strong&gt;: Sends weekly email reports that summarize your website’s media performance. Quickly fix potential issues with these automated alerts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Historical Data Tracking&lt;/strong&gt;: Tracks and analyzes your site's performance metrics over a 90-day period, offering insights into trends and enabling continuous improvement for a better user experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s what a sample report looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhso8irnjri1ziscubv9d.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhso8irnjri1ziscubv9d.jpg" alt="Sample Audit Report" width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The analyzer’s detailed feedback empowers you to make targeted optimizations, resulting in faster websites and better user experiences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internals of ImageKit's Website Performance Analyzer
&lt;/h2&gt;

&lt;p&gt;To evaluate media performance, the analyzer uses weighted scoring for the following audits:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Audit&lt;/th&gt;
&lt;th&gt;Weightage&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Unsized Images&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Prevents layout shifts by ensuring explicit &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Responsive Image Sizing&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Ensures sharp images by serving sizes proportional to display dimensions and DPR.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Properly Sized Images&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;Avoids oversized images, reducing bandwidth usage and load times.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deferring Offscreen Images&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Lazy-loads non-critical images to improve perceived page load speed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modern Image Formats&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;Promotes WebP and AVIF, which reduce file sizes without quality loss.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Optimized Image Encoding&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;Efficient compression accelerates load times and saves data.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Efficient Animated Content&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Encourages replacing GIFs with video for better performance.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modern Video Formats&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Detects VP9/AV1 codecs to ensure optimized playback and bandwidth efficiency.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Most of the audits listed above are standard, except for Modern Video Formats.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Custom Lighthouse Audit for Video Performance
&lt;/h2&gt;

&lt;p&gt;Lighthouse allows extending its capabilities with &lt;a href="https://github.com/GoogleChrome/lighthouse/tree/main/docs/recipes/custom-audit" rel="noopener noreferrer"&gt;custom audits&lt;/a&gt;. We leveraged this to create an audit that detects whether videos are encoded in next-generation formats like VP9 or AV1.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;The audit examines network requests to identify video files and checks if their MIME types match modern formats (e.g., WebM). If outdated formats are detected, the audit flags them and provides actionable feedback.&lt;/p&gt;

&lt;p&gt;Here’s how you can implement it:&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Define the Audit Class
&lt;/h4&gt;

&lt;p&gt;The audit class extends Lighthouse's &lt;code&gt;Audit&lt;/code&gt; class. It defines metadata and the evaluation logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Audit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lighthouse&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VideoOptimizationAudit&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Audit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;modern-video-formats&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Serve videos in modern formats&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;VP9 and AV1 offer better compression compared to H.264.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;requiredArtifacts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;devtoolsLogs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="na"&gt;scoreDisplayMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Audit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SCORING_MODES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BINARY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;audit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;artifacts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Audit logic goes here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VideoOptimizationAudit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2: Implement Audit Logic
&lt;/h4&gt;

&lt;p&gt;The audit evaluates network requests to find videos and checks their MIME types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;audit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;artifacts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;networkRequests&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;artifacts&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;devtoolsLogs&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;defaultPass&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Network.responseReceived&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;videoRequests&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;networkRequests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mimeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Analyze if video mimeType is not webm&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_nonOptimizedVideos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;networkRequests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mimeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mimeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Unique videos based on item?.params?.response?.url because of multiple range requests for same video&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nonOptimizedVideos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_nonOptimizedVideos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nonOptimizedVideos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;displayMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;videoRequests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;nonOptimizedVideos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;displayMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nonOptimizedVideos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; non-optimized videos found`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;videoRequests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;nonOptimizedVideos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;displayMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;All videos are optimized&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;displayMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No videos found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;displayValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;displayMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Audit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeTableDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Video URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="nx"&gt;nonOptimizedVideos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}))),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3: Register the Audit
&lt;/h4&gt;

&lt;p&gt;Include the custom audit in the Lighthouse configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lighthouse:default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;audits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;modern-video-formats&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file as &lt;code&gt;modern-video-formats.js&lt;/code&gt; and run Lighthouse to generate a report with your new custom audit.&lt;/p&gt;

&lt;p&gt;We now have video-specific audit results, which include a list of all videos on the page that are not encoded in next-generation codecs like AV1 or VP9. You can see the full report &lt;a href="https://imagekit.io/website-analyzer/?taskId=7038192c-aaad-447a-9339-33da8b8ae37d&amp;amp;device=mobile" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsi1g0k19r3twvvl2nmiv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsi1g0k19r3twvvl2nmiv.png" alt="Video optimization audit" width="800" height="704"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By extending Lighthouse with a custom audit, you can bridge gaps in performance analysis for videos.&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Try it yourself!&lt;/strong&gt; &lt;a href="https://imagekit.io/website-analyzer/" rel="noopener noreferrer"&gt;Analyze your website’s media performance&lt;/a&gt; and discover actionable insights today.&lt;/p&gt;

</description>
      <category>lighthouse</category>
      <category>webperf</category>
      <category>node</category>
      <category>imagekit</category>
    </item>
    <item>
      <title>Image Optimization - A Practical Guide for Web Developers to Optimize Images</title>
      <dc:creator>Manu Chaudhary</dc:creator>
      <pubDate>Sat, 04 May 2024 08:06:06 +0000</pubDate>
      <link>https://dev.to/manu4543/image-optimization-a-practical-guide-for-web-developers-to-optimize-images-3f6j</link>
      <guid>https://dev.to/manu4543/image-optimization-a-practical-guide-for-web-developers-to-optimize-images-3f6j</guid>
      <description>&lt;p&gt;This guide primarily targets web developers who want to optimize images for media-heavy web and mobile applications. While we will cover some essential theories to solidify your understanding of the core concepts, the main focus of this guide is on practical tips and techniques.&lt;/p&gt;

&lt;p&gt;Based on our extensive experience working with thousands of developers, we have compiled a set of opinionated, actionable recommendations and a checklist to enhance your applications' image performance.&lt;/p&gt;

&lt;p&gt;Ready to dive in? Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Chapter 1 - What is image optimization?
&lt;/h2&gt;

&lt;p&gt;Image optimization is a set of techniques to reduce image file size without compromising "perceived" image quality. The goal is to make images load faster on web and mobile applications. Techniques that are used for image optimization include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Image compression&lt;/strong&gt; - Reducing the file size of an image while maintaining visual quality using lossy compression techniques.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image resizing&lt;/strong&gt; - Changing the dimensions of an image on the server side to fit the application layout on the front end.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image format selection&lt;/strong&gt; - Choosing the right output image format based on the image content and device.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy loading&lt;/strong&gt; - Loading images only when the user is about to see them on the screen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content Delivery Network (CDN)&lt;/strong&gt; - Using a CDN to deliver images faster to users around the world.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will cover each of these techniques in detail in the following chapters. But first, let's see an example and understand why image optimization is important.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick example of image optimization
&lt;/h3&gt;

&lt;p&gt;Let's take this 1.2MB JPEG image as an example and see how we can optimize it using image compression and format selection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Using q to control compression on a scale of 1 to 100 --&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Original image - 1.2MB --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/example_image.jpg?tr=f-jpg,q-100"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Webp with compression - 72 KB --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/example_image.jpg?tr=f-webp,q-80"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- AVIF with compression - 43 KB --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/example_image.jpg?tr=f-avif,q-80"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have put a screenshot instead of rendering actual images because your browser might not support AVIF or WebP format.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HJThI0sZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/image-optimization-example.png%3FupdatedAt%3D1713413904257" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HJThI0sZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/image-optimization-example.png%3FupdatedAt%3D1713413904257" alt="" width="800" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Chapter 2 - Importance of image optimization
&lt;/h2&gt;

&lt;p&gt;It is a no-brainer that images are the most engaging content on the web after video. They help convey information, create visual interest, and improve user engagement. But what if those images are not loaded quickly enough?&lt;/p&gt;

&lt;p&gt;Slow-loading images on a website leads to -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Poor user experience&lt;/strong&gt; - Users are less likely to engage with a website that takes too long to load images.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Higher bounce rates&lt;/strong&gt; - Users are more likely to leave a website if images take too long to load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lower conversion rates&lt;/strong&gt; - Slow-loading images will negatively impact conversion rates on e-commerce websites.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  But what is quick enough?
&lt;/h3&gt;

&lt;p&gt;The answer to this question has been very subjective until recently. The performance is relative, what is fast for one user might be slow for another. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is fast on a high-speed internet connection might be slow on a poor connection.&lt;/li&gt;
&lt;li&gt;What is fast on a high-end desktop might be slow on a low-end mobile device.&lt;/li&gt;
&lt;li&gt;What is fast for a user in the US might be slow for a user in India.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Often, the methods used by engineering teams to measure "speed" are not always accurate. Most of the time, what we measure in a controlled and simulated environment doesn't match the real-world performance.&lt;/p&gt;

&lt;p&gt;This led to the creation of standard user-centric performance metrics that website developers can use to answer the questions confidently - "Is my website fast enough?" and "Are my images loading quickly enough?".&lt;/p&gt;

&lt;p&gt;This is what core web vitals are all about. They are a set of metrics that Google has introduced to measure the user experience on a website. They are based on real-world data and are designed to help developers understand how fast their website is loading for users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chapter 3 - Core web vitals for image performance
&lt;/h2&gt;

&lt;p&gt;Core Web Vitals are the most crucial user-centric performance metrics that site owners should continuously measure and improve. Google has simplified the measurement of these metrics by providing the &lt;a href="https://pagespeed.web.dev/"&gt;Google PageSpeed Insights&lt;/a&gt; tool.&lt;/p&gt;

&lt;p&gt;A typical report of Google PageSpeed Insights looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9F4HozuN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/screenshot-of-core-web-vitals.png%3FupdatedAt%3D1713336644748" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9F4HozuN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/screenshot-of-core-web-vitals.png%3FupdatedAt%3D1713336644748" alt="Screenshot of core web vitals" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Many metrics are part of &lt;a href="https://web.dev/articles/vitals"&gt;Core Web Vitals&lt;/a&gt;, but image optimization has a direct impact on Largest Contentful Paint (LCP) and First Contentful Paint (FCP).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Largest Contentful Paint (LCP)
&lt;/h3&gt;

&lt;p&gt;It represents how quickly the main content of a web page loads, specifically, the time from when the user initiates loading the page until the largest image or text block is rendered within the viewport. To provide a good user experience, LCP should occur within 2.5 seconds of when the page first starts loading. Fast-loading images will have a direct positive impact on this metric.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JmFOb1ce--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/lcp.png%3FupdatedAt%3D1713337648051" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JmFOb1ce--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/lcp.png%3FupdatedAt%3D1713337648051" alt="Source web.dev" width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  First Contentful Paint (FCP)
&lt;/h3&gt;

&lt;p&gt;It marks the time at which the first content is painted. It is the first impression of the website. For this metric, "content" refers to text, images (including background images), elements, or non-white elements. If you have an image like a banner at the top of the page, its loading time will directly impact the FCP. To provide a good user experience, pages should have a FCP of less than 1.8 seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mtm2WMCc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/fcp.png%3FupdatedAt%3D1713337648051" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mtm2WMCc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/fcp.png%3FupdatedAt%3D1713337648051" alt="Source web.dev" width="800" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Chapter 4 - Image optimization Checklist
&lt;/h2&gt;

&lt;p&gt;Here is a checklist for your team to ensure that images on your website are optimized for performance. This checklist is based on the best practices and techniques we will cover in the following chapters.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;Task&lt;/th&gt;
    &lt;th&gt;Description&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Compress images&lt;br&gt;&lt;code&gt;HIGH IMPORTANCE&lt;/code&gt;
&lt;/td&gt;
    &lt;td&gt;Choosing the correct compression settings allows for a balance between image quality and file size, which speeds up image loading without compromising visual clarity.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Adopt WebP/AVIF&lt;br&gt;&lt;code&gt;HIGH IMPORTANCE&lt;/code&gt;
&lt;/td&gt;
    &lt;td&gt;Modern image formats like WebP or AVIF can significantly reduce file size while maintaining high-quality visuals, leading to faster loading times.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Correctly resize images on server-side&lt;br&gt;&lt;code&gt;HIGH IMPORTANCE&lt;/code&gt;
&lt;/td&gt;
    &lt;td&gt;Serving images at the correct dimensions reduces unnecessary data overhead, enhancing speed and efficiency in image delivery&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Utilize a CDN&lt;br&gt;&lt;code&gt;HIGH IMPORTANCE&lt;/code&gt;
&lt;/td&gt;
    &lt;td&gt;A Content Delivery Network (CDN) enhances image delivery by serving them from a server closest to the user. This proximity significantly reduces load times and improves response rates, optimizing the user experience across different global locations.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Implement responsive images&lt;br&gt;&lt;code&gt;MEDIUM IMPORTANCE&lt;/code&gt;
&lt;/td&gt;
    &lt;td&gt;Ensure that your application loads the right image. Consider implementing responsive images using srcset and size attributes.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Replace GIFs with video&lt;br&gt;&lt;code&gt;MEDIUM IMPORTANCE&lt;/code&gt;
&lt;/td&gt;
    &lt;td&gt;Replacing GIFs with videos or animated WebP reduces file size and load times while saving bandwidth costs.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Set image dimensions&lt;br&gt;&lt;code&gt;MEDIUM IMPORTANCE&lt;/code&gt;
&lt;/td&gt;
    &lt;td&gt;Specifying width and height on images prevents layout shifts during loading, improving user experience and Cumulative Layout Shift scores.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Use SVGs for icons&lt;br&gt;&lt;code&gt;MEDIUM IMPORTANCE&lt;/code&gt;
&lt;/td&gt;
    &lt;td&gt;Vector images like SVGs are ideal for logos and icons as they scale without losing quality, are smaller in file size, and render sharply on all screen resolutions.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Implement lazy loading&lt;br&gt;&lt;code&gt;MEDIUM IMPORTANCE&lt;/code&gt;
&lt;/td&gt;
    &lt;td&gt;Lazy loading defers loading of images until they are in or near the viewport, reducing initial load time and saving bandwidth costs.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Use preconnect and priority hints&lt;br&gt;&lt;code&gt;LOW IMPORTANCE&lt;/code&gt;
&lt;/td&gt;
    &lt;td&gt;Preconnect hints enable the browser to establish early connections to domains hosting images, which accelerates image loading when accessed by users. Additionally, using &lt;a href="https://web.dev/articles/fetch-priority"&gt;priority hint&lt;/a&gt; to prioritize images at the top of the page can enhance the Largest Contentful Paint (LCP), significantly improving the perceived load speed of the page.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Monitor relevant Core Web Vitals&lt;br&gt;&lt;code&gt;HIGH IMPORTANCE&lt;/code&gt;
&lt;/td&gt;
    &lt;td&gt;Tracking relevant Core Web Vitals helps identify areas for improvement, ensuring optimal user experience and SEO rankings.&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Chapter 5 - Compress images
&lt;/h2&gt;

&lt;p&gt;Image compression is the process of reducing the file size of an image without significantly affecting its visual quality. There are two types of image compression techniques:&lt;/p&gt;

&lt;h3&gt;
  
  
  Lossy Compression
&lt;/h3&gt;

&lt;p&gt;Lossy compression reduces file sizes by permanently removing certain information and details from image files. While this can affect image quality, the degree of quality loss can be controlled and is often imperceptible, making the trade-off in size reduction very advantageous for web usage.&lt;/p&gt;

&lt;p&gt;Predominantly used in web applications, lossy compression is ideal for balancing image quality with load speed, thereby enhancing user experience and reducing data costs. Formats such as JPEG and WebP are commonly used for lossy compression. These are suitable for photographs and detailed images where a slight loss of quality is acceptable in exchange for significantly smaller file sizes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why does lossy compression work really well for web use cases?
&lt;/h4&gt;

&lt;p&gt;Let's compress a 1.2MB JPEG image at different compression levels and see the difference:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyd6a1xg6us8i8b3coir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyd6a1xg6us8i8b3coir.png" alt="Image description" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You won't notice any difference between the original image (leftmost) and the compressed images, although the file sizes vary significantly. This demonstrates the effectiveness of lossy compression for web use, as it reduces file size dramatically without a noticeable change in "perceived" quality to the human eye.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You should avoid extreme image compression, as there is an optimal balance between file size and quality. Excessive compression results in poor visual quality, negatively impacting user experience. An image CDN like ImageKit.io is valuable for its real-time optimization capabilities. It automatically compresses images to the appropriate level, which balances visual quality &amp;amp; size and allows you to control this compression based on your business requirements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Lossless Compression
&lt;/h3&gt;

&lt;p&gt;Lossless compression reduces file size without any loss of information. It optimizes the image data by repackaging redundant data and removing unnecessary metadata, ensuring that the original data can be perfectly reconstructed from the compressed data. Lossless compression is crucial for archiving images where preserving the original quality is essential. It is also recommended for images that undergo multiple edits, as it prevents the quality degradation that can occur with repeated saving.&lt;/p&gt;

&lt;p&gt;PNG and TIFF are typical formats that employ lossless compression. They are preferred for images requiring high precision and clarity, such as digital graphics, logos, and line art.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We don't recommend using lossless compression for web use cases.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  How to compress images?
&lt;/h3&gt;

&lt;p&gt;There are many online and offline tools available to compress images. We highly recommend using only the online tools or an Image CDN as they don't require installation.&lt;/p&gt;

&lt;p&gt;Depending on the use case, you can choose the right tool for compressing images:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;th&gt;Use-case&lt;/th&gt;
            &lt;th&gt;Tool&lt;/th&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;Very few images. One-time optimization is required.&lt;/td&gt;
            &lt;td&gt;
&lt;a href="https://tinypng.com/"&gt;TinyPNG&lt;/a&gt; and &lt;a href="https://squoosh.app/"&gt;Squoosh&lt;/a&gt;.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;E-commerce website&lt;/td&gt;
            &lt;td&gt;
                Depending on the platform, there could be some built-in optimizations. However, platforms like Magento,
                WordPress, and Shopify often result in poor visual quality of the images. We recommend using an image CDN like ImageKit.io. For more details on how to display high-quality e-commerce product images, &lt;a href="https://imagekit.io/how-to-show-high-quality-e-commerce-product-images/"&gt; checkout this blog&lt;/a&gt;.
                &lt;br&gt;
                &lt;br&gt;
                &lt;ul&gt;
                  &lt;li&gt;
                    Learn how Nykaa simplified image management and optimization for their websites and apps. &lt;a href="https://imagekit.io/blog/nykaa-image-management-optimization-imagekit-case-study/"&gt;Case study&lt;/a&gt;.
                  &lt;/li&gt;
                  &lt;li&gt;
                    Lenskart leveraged better visual experience to improve conversion and global expansion. &lt;a href="https://imagekit.io/blog/how-lenskart-improved-conversion-and-global-expansion-using-better-visual-experience/"&gt;Case study&lt;/a&gt;.
                  &lt;/li&gt;
                &lt;/ul&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;Custom media-heavy web application&lt;/td&gt;
            &lt;td&gt;
              Use an image CDN to automate image
                optimization. This allows your engineering team to focus on building an engaging visual experience
                without dealing with its technical complexities.
                &lt;br&gt;
                &lt;br&gt;
                &lt;ul&gt;
                  &lt;li&gt;
                    Checkout how Swiggy enhanced performance, personalized UX, and saved costs across platforms. &lt;a href="https://imagekit.io/blog/swiggy-imagekit-case-study/"&gt;Case study&lt;/a&gt;.
                  &lt;/li&gt;
                  &lt;li&gt;
                    Learn how Curtsy improved customer engagement and transactions with personalized banners. &lt;a href="https://imagekit.io/blog/improving-customer-engagement-and-transactions-with-personalized-banners-curtsy-case-study/"&gt;Case study&lt;/a&gt;.
                  &lt;/li&gt;
                &lt;/ul&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;User-generated content&lt;/td&gt;
            &lt;td&gt;
                To manage user-generated content effectively, you have two options for image compression: compress at
                the time of upload and store the compressed images, or use on-the-fly compression via an image CDN. For storage, consider using cloud-based object storage like S3 or opt for ImageKit's Media Library. ImageKit's &lt;a href="https://imagekit.io/blog/image-storage-api/"&gt;storage API&lt;/a&gt; allows you to compress images and apply various transformations during uploading. You can use the generated media file URLs directly in your application.
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;You should always store high-quality master images at the largest resolution needed for desktop use, typically around 1920px wide and under 5MB. This approach lets you tweak compression settings later without losing the original image quality. Having an image CDN that can compress images on the fly is recommended, as it gives your engineering team the flexibility to adjust compression settings without altering the original image.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Chapter 6 - Optimizing image format
&lt;/h2&gt;

&lt;p&gt;Optimizing image format means converting the input image to the right output format before delivering it to the user.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the right image format?
&lt;/h3&gt;

&lt;p&gt;Well, it depends on a lot of things. You should consider the following factors - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Browser and device support&lt;/strong&gt; - Does the browser support modern image formats like WebP and AVIF?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transparency&lt;/strong&gt; - Does the image require transparency? JPEG doesn't support transparency, so possible options are PNG, WebP, and AVIF.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Animation&lt;/strong&gt; - Does the image require animation? GIF and WebP support animation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compression/File size&lt;/strong&gt; - AVIF is the clear winner in terms of compression and file size. WebP is also good. JPEG is the worst relatively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality&lt;/strong&gt; - At similar compression levels, which format delivers superior quality? AVIF leads in quality, with WebP also performing well.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, the definition of the right image format becomes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The right image format is the one that provides high quality and the smallest file size based on the image content and device support. This means that AVIF may be suitable for some users, and JPEG may be the better choice for others.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is easy to get overwhelmed by these factors. But don't worry; follow these guidelines, and you will be good:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use SVG for icons, simple graphics, and logos. A vector image is resolution-independent, so it can be scaled to any size without losing quality. All modern browsers support it.&lt;/li&gt;
&lt;li&gt;For photographs and images with complex color gradients, i.e., typical real-world images, AVIF should be preferred. Use WebP as a decent fallback because it is now widely supported. Use JPEG as a last resort for very older browsers and devices.&lt;/li&gt;
&lt;li&gt;For images requiring transparency, use AVIF or WebP. PNG should be your last preference.&lt;/li&gt;
&lt;li&gt;Avoid using GIFs altogether. Convert GIF to MP4 video or animated WebP.&lt;/li&gt;
&lt;li&gt;If you use a content delivery network (CDN), which you should be, then correctly configure caching rules so images are not delivered in unsupported image format from polluted CDN cache. We will talk more about this in the coming chapters.&lt;/li&gt;
&lt;li&gt;Above all, make sure your application logic is simple. Handle complexity on the server-side.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're setting up an in-house image processing service, consider the high infrastructure costs, especially for computationally intensive tasks like encoding images in AVIF format. An image CDN like ImageKit.io can streamline image processing for you and efficiently handle scaling during traffic spikes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to handle browser support and serve image in the best possible format?
&lt;/h2&gt;

&lt;p&gt;We talked about serving different image formats based on the browser support. But how do you do that?&lt;/p&gt;

&lt;p&gt;Technically, you can do it in two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Using HTML &lt;code&gt;picture&lt;/code&gt; element&lt;/strong&gt; - The &lt;code&gt;picture&lt;/code&gt; element allows you to define multiple sources for an image based on different conditions. You can use it to serve different format images based on browser support.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"image.avif"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/avif"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"image.webp"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"An awesome image"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Using ImageKit.io&lt;/strong&gt; - ImageKit.io is an image CDN that can automatically convert images to the right format based on the factors we discussed above. You don't have to change the image URL. This is done by changing the format on the fly and correctly setting the &lt;code&gt;Content-Type&lt;/code&gt; response header based on format support declared by the browser in the &lt;code&gt;Accept&lt;/code&gt; request header.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/example_image.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What's wrong with using picture element?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The problem with using the &lt;code&gt;picture&lt;/code&gt; element to serve different formats is that it increases the HTML markup. If you are doing server-side rendering, all users will have to download this extra markup when every page loads.&lt;/li&gt;
&lt;li&gt;Another problem is generating and storing multiple variants for the same image. What if a new format comes up tomorrow? You will have to update all the images. This needs to be more scalable.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The second approach is using an &lt;a href="https://imagekit.io"&gt;image CDN&lt;/a&gt;. It always delivers an image in the right format, considering all the above factors. You don't have to change the image URL. In addition, you can control the output format via URL parameters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  How to convert GIF to video or animated WebP?
&lt;/h3&gt;

&lt;p&gt;GIF is not an ideal web format due to its large file size and limited color palette, which supports only 256 colors. It also lack modern features like transparency. For better performance and quality, it is recommended that GIFs be converted to video formats or animated WebP.&lt;/p&gt;

&lt;p&gt;Let's convert this GIF - &lt;a href="https://ik.imagekit.io/demo/gif-test.gif"&gt;https://ik.imagekit.io/demo/gif-test.gif&lt;/a&gt; to webm video and animated WebP to compare sizes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a-KfQpYH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/gif.png%3FupdatedAt%3D17136850488663" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a-KfQpYH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/gif.png%3FupdatedAt%3D17136850488663" alt="Original GIF - 2.3MB" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2e4y8-fb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/webm-video.png%3FupdatedAt%3D17136850488932" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2e4y8-fb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/webm-video.png%3FupdatedAt%3D17136850488932" alt="WebM Video - 165KB" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RQ_1yBwe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/animated-webp.png%3FupdatedAt%3D17136850348509" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RQ_1yBwe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/animated-webp.png%3FupdatedAt%3D17136850348509" alt="Animated WebP - 1.4MB" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stark difference in file sizes, right? 2.3MB Gif vs 165KB WebM video vs 1.4MB Animated WebP.&lt;/p&gt;

&lt;h4&gt;
  
  
  Convert GIF to video using ImageKit
&lt;/h4&gt;

&lt;p&gt;Use ImageKit &lt;a href="https://docs.imagekit.io/features/video-transformation/resize-crop-and-other-common-video-transformations#gif-to-mp4"&gt;GIF to video&lt;/a&gt; conversion feature to convert GIF to video. You can then use the HTML5 video tag for playback. ImageKit will automatically take care of video codec and serve &lt;a href="https://imagekit.io/blog/vp9-codec/"&gt;VP9&lt;/a&gt; or &lt;a href="https://imagekit.io/blog/av1-codec/"&gt;AV1&lt;/a&gt; encoded video if browser supports it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;video&lt;/span&gt; &lt;span class="na"&gt;autoplay&lt;/span&gt; &lt;span class="na"&gt;loop&lt;/span&gt; &lt;span class="na"&gt;muted&lt;/span&gt; &lt;span class="na"&gt;playsinline&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/demo/gif-test.gif/ik-gif-video.mp4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/video&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Convert GIF to animated WebP
&lt;/h4&gt;

&lt;p&gt;When images are delivered using ImageKit, a GIF is automatically converted to animated WebP for supported browsers. You don't have to do anything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/demo/gif-test.gif"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Chapter 7 - Resizing images to fit the layout
&lt;/h2&gt;

&lt;p&gt;Resizing an image means changing its dimensions on the server-side per layout requirements before delivering it to the user. Many of us have inadvertently uploaded full-size images directly onto web pages. This is an easy mistake to make, especially when fast internet speeds make large images appear to load swiftly and display properly. However, in practical scenarios, this can significantly degrade performance as users are forced to download excessive data, impacting their experience negatively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why resize images on server-side?
&lt;/h3&gt;

&lt;p&gt;Simply put, resizing images to fit the layout is important because it reduces the image's resolution, meaning there are fewer pixels to encode, which results in a smaller file size. Serving a 2000x2000 image in a 200x200 container is inefficient, wasting bandwidth and slowing down image loading times for your users.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to resize images?
&lt;/h2&gt;

&lt;p&gt;No matter how your media workflow looks, there are only two ways to serve correctly resized images: either you generate and store the correct-size image in advance, or you generate it on the fly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pre-emptive resizing -  In this approach, you generate and store multiple variants of the image based on the current application layout (and future needs). This is a good approach if you have a static layout that won't change. However, it is not scalable, and you will end up storing multiple copies of the same image.&lt;/li&gt;
&lt;li&gt;On-the-fly resizing - With this approach, you only store the original image and resize it on the fly based on the application layout. This method is highly scalable and recommended for most use cases because it adapts to varying UI changes and device targets without the need to pre-generate and store every possible image variation. This saves on storage and ensures images are optimally sized in real time, catering to the high variability in user devices.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pre-emptive resizing using ImageMagick
&lt;/h3&gt;

&lt;p&gt;If there are only a handful of images, use any online image resizing tool. For media-heavy use use-cases, you can programmatically resize images at the time of ingestion and store multiple variants.&lt;/p&gt;

&lt;p&gt;To resize all images in a folder to specific dimensions using ImageMagick from the command line, you can use the &lt;code&gt;mogrify&lt;/code&gt; command. &lt;code&gt;mogrify&lt;/code&gt; is part of the ImageMagick suite of tools, and it is used for batch processing of image files. Here's how you can do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/your/images
mogrify &lt;span class="nt"&gt;-resize&lt;/span&gt; 200x200 &lt;span class="k"&gt;*&lt;/span&gt;.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The mogrify command modifies images in place, meaning it will overwrite the original files. It's a good practice to back up your images before running the command, especially if you are not sure about the changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  How to resize images on the fly?
&lt;/h3&gt;

&lt;p&gt;On-the-fly resizing is the most scalable approach. You don't have to worry about storing multiple variants of the same image. You can resize images on the fly using an image CDN like ImageKit.io or by implementing an image resizing service yourself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy69yttrpmpbegd4lkzg2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy69yttrpmpbegd4lkzg2.gif" alt="Image description" width="620" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Basic resizing 200x200 thumbnail
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/example_image.jpg?tr=w-200,h-200"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  AI-based smart cropping to generate meaningful thumbnails
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/example_image.jpg?tr=w-200,h-200,fo-auto"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;See the different &lt;a href="https://docs.imagekit.io/features/image-transformations"&gt;image transformations&lt;/a&gt; available in ImageKit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to load the correct image in your application?
&lt;/h2&gt;

&lt;p&gt;We've discussed resizing images to make them suitable for your application. But how do you ensure the correct image loads on each device?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your application's layout is simple and consistent across different screen sizes, you can load the image using the &lt;code&gt;src&lt;/code&gt; attribute. This technique also works on single-page applications (SPAs) where JavaScript generates the layout.&lt;/li&gt;
&lt;li&gt;If the layout is complex and adjusts based on screen size and display density, you should use the &lt;code&gt;srcset&lt;/code&gt; attribute. This lets you specify multiple image options, ensuring the most suitable one is loaded based on the device's screen size. This technique is part of implementing &lt;a href="https://imagekit.io/responsive-images/"&gt;responsive images&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implementing responsive images
&lt;/h3&gt;

&lt;p&gt;Responsive images are the set of techniques used to load the right image based on device resolution, orientation, screen size, network connection, and page layout. The browser should load an image that fits the layout, and loading it shouldn't result in time &amp;amp; bandwidth wastage. It improves user experience as images load fast and looks crisp to the human eye.&lt;/p&gt;

&lt;p&gt;We have written an end-to-end guide on &lt;a href="https://imagekit.io/responsive-images"&gt;responsive images&lt;/a&gt;, but here is what you need to know - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;srcset&lt;/code&gt; with &lt;code&gt;sizes&lt;/code&gt; to let the browser load the right image based on the device's screen size and application layout. This forces you to consider layout and image dimensions.&lt;/li&gt;
&lt;li&gt;Avoid using the &lt;code&gt;picture&lt;/code&gt; element and Client Hints to automate responsive image implementation. This method looks promising on the surface, but it will end up creating too many close variants of the same image.&lt;/li&gt;
&lt;li&gt;In most cases, &lt;a href="https://observablehq.com/@eeeps/visual-acuity-and-device-pixel-ratio"&gt;the human eye cannot discern the benefits of a Device Pixel Ratio (DPR) of 3&lt;/a&gt;, allowing for the use of smaller images without noticeably reducing quality for the majority of users. Limit serving only 2x images for high-density screens like Retina displays.&lt;/li&gt;
&lt;li&gt;Regardless of the chosen method, select breakpoints thoughtfully and maintain straightforward logic. Focus on your users' most common screen sizes and tailor your images to those dimensions. Creating too many variants of the same image can hinder CDN caching and unnecessarily burden the server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What is wrong with resizing in HTML using width and height attribute?
&lt;/h3&gt;

&lt;p&gt;Resizing images in HTML using the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes is not recommended. It is a bad practice because the browser downloads the full-size image and then resizes it to fit the layout. This wastes bandwidth and slows down page load times. Always resize images on the server-side before delivering them to the user. Furthermore, a browser-resized image might not look as good and sharp as a server-resized image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chapter 8 - Lazy loading images
&lt;/h2&gt;

&lt;p&gt;Lazy Loading Images is a set of techniques in web and application development that defer the loading of images on a page to a later point in time - when those images are actually needed, instead of loading them upfront. These techniques help improve performance, better utilize the device's resources, and reduce associated delivery costs.&lt;/p&gt;

&lt;p&gt;We have written a detailed guide on &lt;a href="https://imagekit.io/blog/lazy-loading-images-complete-guide/"&gt;lazy loading images&lt;/a&gt;, but here is the gist in the context of image performance.&lt;/p&gt;

&lt;p&gt;Primarily, there are two advantages of lazy loading images:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance improvement&lt;/strong&gt; - This one is obvious. If a page loads fewer resources, then the important resources like CSS, JS, and images on the top will load faster, improving the overall user experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost reduction&lt;/strong&gt; - Serving images from a CDN, S3, web-server or any other provider costs money. If the user never scrolls to the bottom of the page, then why load those images? Lazy-loading images will save you money.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to lazy load images?
&lt;/h2&gt;

&lt;p&gt;There are &lt;a href="https://imagekit.io/blog/lazy-loading-images-complete-guide/#lazy-loading-techniques-for-images"&gt;multiple ways to lazy load images&lt;/a&gt;, but we will suggest you go with the following two:&lt;/p&gt;

&lt;h3&gt;
  
  
  Native Lazy Loading
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;loading&lt;/code&gt; attribute on the &lt;code&gt;img&lt;/code&gt; tag is a native browser feature that allows you to lazy load images without any JavaScript. It is supported in Chrome, Edge, and Firefox.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T6-30i0Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/lazy-loading-support.png%3FupdatedAt%3D1713755224489" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T6-30i0Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/lazy-loading-support.png%3FupdatedAt%3D1713755224489" alt="Browser support - caniuse.com" width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is how you can use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"example.jpg"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;lazy&lt;/strong&gt; - Deferring the loading of assets till it reaches a certain distance from the viewport.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;eager&lt;/strong&gt; - loading the assets as soon as the page loads, irrespective of where they are placed on the page, whether above or below the page fold.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;auto&lt;/strong&gt; - This value triggers default lazy loading. Basically, it's the same as not including the loading attribute.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Intersection Observer API
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API"&gt;Intersection Observer API&lt;/a&gt; is a JavaScript API that allows you to observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport. It is supported in all modern browsers.&lt;/p&gt;

&lt;p&gt;Here is a working CodePen example taken from our &lt;a href="https://imagekit.io/blog/lazy-loading-images-complete-guide/#using-intersection-observer-api-to-trigger-image-loads"&gt;blog post&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;See the Pen &lt;a href="https://codepen.io/imagekit_io/pen/BPXQZZ"&gt;&lt;br&gt;
 Lazy loading images using IntersectionObserver - example code&lt;/a&gt; by ImageKit.io (&lt;a href="https://codepen.io/imagekit_io"&gt;@imagekit_io&lt;/a&gt;)&lt;br&gt;
 on &lt;a href="https://codepen.io"&gt;CodePen&lt;/a&gt;.&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;We recommend using the native lazy loading attribute as it is supported in most modern browsers. If you need more control, then use the Intersection Observer API. Loading extra JavaScript for lazy loading images is no longer recommended.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you are using ImageKit front-end SDKs (React, Angular, Vue.js), check the following getting-started guides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lazy loading images in &lt;a href="https://docs.imagekit.io/getting-started/quickstart-guides/react#lazy-loading-images-in-react"&gt;React&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Lazy loading images in &lt;a href="https://docs.imagekit.io/getting-started/quickstart-guides/angular#lazy-loading-images-in-angular"&gt;Angular&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Lazy loading images in &lt;a href="https://docs.imagekit.io/getting-started/quickstart-guides/vuejs#lazy-loading-images-in-vue.js"&gt;Vue.js&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Chapter 9 - Using CDN for fast download
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://imagekit.io/blog/what-is-content-delivery-network-cdn-guide/"&gt;Content Delivery Network&lt;/a&gt; (CDN) is a network of servers distributed across the globe that cache and deliver content to users based on their geographic location. CDNs are used to deliver content, including images, videos, and other static assets, faster to users around the world.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why use a CDN for images?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster delivery&lt;/strong&gt; - CDNs cache images on servers closer to the user, reducing latency and improving load times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt; - CDNs can handle large volumes of traffic and scale automatically to meet demand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability&lt;/strong&gt; - CDNs provide redundancy and failover protection, ensuring that images are always available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt; - CDNs offer security features like DDoS protection and SSL encryption to protect your web server from common attacks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to configure CDN for images?
&lt;/h2&gt;

&lt;p&gt;Configuring a CDN for images depends on the CDN provider and your image server configuration. In general, here are the factors to keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your server changes format on the same URL based on the request &lt;code&gt;Accept&lt;/code&gt; header, then send the &lt;code&gt;Vary: Accept&lt;/code&gt; response header to cache a different image copy on the CDN. This is important if you serve WebP, AVIF, and JPEG images on the same resource URL. Most CDN providers support this standard except Akamai and Azure CDN from Microsoft.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;Cache-Control&lt;/code&gt; header to set the cache duration for images. You can set it to a year for images that don't change frequently.&lt;/li&gt;
&lt;li&gt;Correctly set the &lt;code&gt;Content-Type&lt;/code&gt; header based on the image format.&lt;/li&gt;
&lt;li&gt;Avoid modifying content based on the &lt;code&gt;User-Agent&lt;/code&gt; request header. First, it is not 100% reliable, and second, it will hit the cache-hit ratio adversely.&lt;/li&gt;
&lt;li&gt;If possible, use CloudFront functions or something similar to normalize the image URL and cache key before caching. This will help in the cache-hit ratio.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The exact steps to configure a CDN for images could vary from provider to provider, and it can be tricky to get it right. We recommend using an image CDN like ImageKit.io, which automatically takes care of these things for you. It comes with CloudFront CDN.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Chapter 10 - Platform-specific image optimization
&lt;/h2&gt;

&lt;p&gt;Most site generators and e-commerce platforms have built-in image optimization features. However, they all lack the control and flexibility you need as a web developer to ensure the best image performance. Let's compare some popular platforms and the ideal way to automate image encoding and optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Image optimization in Next.js
&lt;/h2&gt;

&lt;p&gt;Next.js is a popular React framework that provides server-side rendering and static site generation. The Next.js &lt;code&gt;Image&lt;/code&gt; component extends the HTML &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element with features for automatic image optimization:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Format Optimization: Automatically deliver images in the optimal format for each device, utilizing modern formats such as WebP and AVIF.&lt;/li&gt;
&lt;li&gt;Visual Stability: Automatically prevent layout shifts during image loading.&lt;/li&gt;
&lt;li&gt;Lazy Loading: Images load only when they become visible in the viewport, utilizing native browser lazy loading techniques, complemented by optional blur-up placeholders.&lt;/li&gt;
&lt;li&gt;Server-Side Resizing: Perform on-demand resizing of images using the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;You can use Next.js built-in optimizations for a small site. For a media-heavy site, you should use an image CDN like ImageKit.io to automate image optimization. Next.js provides custom loader support, so you can use ImageKit.io as a custom loader to serve optimized images.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is an example of using ImageKit as a custom loader in Next.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Image&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageKitLoader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quality&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`w-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`q-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paramsString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;urlEndpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://ik.imagekit.io/your_imagekit_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;urlEndpoint&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;urlEndpoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;urlEndpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;urlEndpoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;urlEndpoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;urlEndpoint&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?tr=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paramsString&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Image&lt;/span&gt;
      &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;imageKitLoader&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;default-image.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sample image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other useful resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js image optimization &lt;a href="https://imagekit.io/blog/nextjs-image-optimization/"&gt;blog post&lt;/a&gt; and &lt;a href="https://docs.imagekit.io/getting-started/quickstart-guides/nextjs"&gt;getting started guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Automate &lt;a href="https://docs.imagekit.io/platform-guides/wordpress"&gt;image optimization in WordPress&lt;/a&gt; using ImageKit plugin.&lt;/li&gt;
&lt;li&gt;Load high-quality compressed product images on &lt;a href="https://docs.imagekit.io/platform-guides/shopify"&gt;Shopify&lt;/a&gt; and &lt;a href="https://docs.imagekit.io/platform-guides/magento"&gt;Magento&lt;/a&gt; using ImageKit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion - Why use an image CDN like ImageKit?
&lt;/h2&gt;

&lt;p&gt;To complete image optimization checklist, your engineering team needs a powerful media API to automate most image optimization and transformation tasks. This is where an image CDN comes into play.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automate image format selection and compression
&lt;/h3&gt;

&lt;p&gt;ImageKit's automatic format conversion and optimal compression reduce significant complexity for your web developers. Based on multiple factors, including browser support, ImageKit can deliver WebP, AVIF, and JPEG images on the same image URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TQ0ONPNp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/format-optimization-example.png%3FupdatedAt%3D1713758900447" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TQ0ONPNp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ikmedia.imagekit.io/site-guides/format-optimization-example.png%3FupdatedAt%3D1713758900447" alt="Loading different image format in Chrome vs Safari on same image URL" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means you don't have to worry about how to modify HTML to request the correct image or how to store multiple variants of the same image. ImageKit takes care of it for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  On-the-fly resizing for responsive images
&lt;/h3&gt;

&lt;p&gt;Implementing responsive images using &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt; is a relatively complex task. Your team also has to worry about the generation and storage of all the variants. ImageKit can resize images on the fly based on URL parameters, making it easy to serve correctly sized images.&lt;/p&gt;

&lt;p&gt;For example, to resize an image to 200x200 pixels, you can use the following URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/example_image.jpg?tr=w-200,h-200"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To resize an image to 200x200 pixels and apply smart cropping, you can use the following URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/example_image.jpg?tr=w-200,h-200,fo-auto"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add a text overlay on the image, you can use the following URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/example_image.jpg?tr=w-200,h-200,l-text,i-hello,l-end"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An example picked from our &lt;a href="https://imagekit.io/blog/css-image-overlay/"&gt;text overlay blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5RcRp2-4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ik.imagekit.io/ikmedia/hoodie_white.png%3Ftr%3Dw-394%2Ch-540%2Cl-text%2Ci-15%25%2520OFF%2Cco-FFFFFF%2Cbg-EF6823%2Cr-4%2Cpa-8_8%2Clx-10%2Cly-10%2Ctg-bold%2Cfs-30%2Cl-end" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5RcRp2-4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ik.imagekit.io/ikmedia/hoodie_white.png%3Ftr%3Dw-394%2Ch-540%2Cl-text%2Ci-15%25%2520OFF%2Cco-FFFFFF%2Cbg-EF6823%2Cr-4%2Cpa-8_8%2Clx-10%2Cly-10%2Ctg-bold%2Cfs-30%2Cl-end" alt="" width="394" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is just the tip of the iceberg. ImageKit provides a wide range of &lt;a href="https://docs.imagekit.io/features/image-transformations"&gt;image transformations&lt;/a&gt; that can be applied on the fly. Bonus: The same API works on &lt;a href="https://docs.imagekit.io/features/video-transformation"&gt;videos&lt;/a&gt;, making it a one-stop solution for all your media needs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;h2&gt;
  
  
  How to monitor image performance?
&lt;/h2&gt;

&lt;p&gt;We recommend using &lt;a href="https://pagespeed.web.dev/"&gt;Google PageSpeed Insights&lt;/a&gt; to monitor image performance. It provides a detailed report on how images are affecting your website's performance. You can also use &lt;a href="https://developers.google.com/web/tools/lighthouse"&gt;Lighthouse&lt;/a&gt; for a more in-depth analysis. Optimize large contentful paint (LCP) and first contentful paint (FCP) to improve image performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to optimize images for SEO?
&lt;/h2&gt;

&lt;p&gt;Use sensible file names and alt text for images. Use descriptive file names that include relevant keywords. Add alt text to images to describe the content of the image. This helps search engines understand the context of the image and improves SEO.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Data-Saver mode in Chrome?
&lt;/h2&gt;

&lt;p&gt;Mobile browsers like Chrome Mobile and Opera Mobile allow users to activate a Data Saver mode. With this mode enabled, the browser sends a &lt;code&gt;Save-data&lt;/code&gt; header within the request. By identifying this header, a web page can customize and deliver an optimized user experience to cost—and performance-constrained users.&lt;/p&gt;

&lt;p&gt;ImageKit supports &lt;a href="https://docs.imagekit.io/features/image-optimization/data-saver-mode"&gt;Data Saver mode&lt;/a&gt; to further optimize images for users on slow connections.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webperf</category>
      <category>imageoptimization</category>
    </item>
    <item>
      <title>Image resizing in Java</title>
      <dc:creator>Manu Chaudhary</dc:creator>
      <pubDate>Sun, 20 Dec 2020 05:59:31 +0000</pubDate>
      <link>https://dev.to/manu4543/image-resizing-in-java-5apd</link>
      <guid>https://dev.to/manu4543/image-resizing-in-java-5apd</guid>
      <description>&lt;p&gt;There are a couple of ways to resize &amp;amp; crop images in Java. This article will briefly compare different methods of resizing images in Java, along with pros and cons.&lt;/p&gt;

&lt;p&gt;More importantly, after you finish reading, you will learn a novel approach to resizing images in Java applications, which doesn’t require writing any image resizing code or maintaining servers to handle a large volume of image manipulation requests.&lt;/p&gt;

&lt;p&gt;There are broadly four ways to resize images in Java:-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Native Java&lt;/strong&gt; -It does not require any third-party libraries.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Open-source image manipulation libraries&lt;/strong&gt; - For example, ImageMagick.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Open-source imaging service&lt;/strong&gt; like Thumbor.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Free and paid Image CDN&lt;/strong&gt; e.g. ImageKit.io.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Method&lt;/th&gt;

&lt;th&gt;Pros&lt;/th&gt;

&lt;th&gt;Cons&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;Native Java functions&lt;/td&gt;

&lt;td&gt;- No third party library is required.&lt;/td&gt;

&lt;td&gt;You will have to deal with a lot of low-level image processing and file operation.&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;Open source image processing libraries&lt;/td&gt;

&lt;td&gt;- High image quality.  
- More control over resizing and cropping options.  
- Advance features e.g. watermarking and text overlay.&lt;/td&gt;

&lt;td&gt;You will have to install third-party libraries and find relevant options to get the desired results.&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;Open source thumbnail general service&lt;/td&gt;

&lt;td&gt;- Expressive API to resize &amp;amp; crop images for web pages.  
- High image quality.  
- More control over resizing and cropping options.&lt;/td&gt;

&lt;td&gt;You will have to install a third-party service and maintain the infrastructure.&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;Free or paid image CDN&lt;/td&gt;

&lt;td&gt;- No third party image processing library required.  
- Since you are not running the service, you don’t have to maintain the infrastructure.  
- Get started within a few minutes.  
- Expressive API to resize &amp;amp; crop images for web pages.  
- Advance features such as smart cropping and face detection.  
- More control over resizing and cropping options.  
- High image quality.&lt;/td&gt;

&lt;td&gt;An overkill if you want to resize a handful of images. If you are serving images on the web, then you should be using an image CDN.&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In this post, we will deep dive into different methods of resizing and cropping using ImageKit.io URL-parameters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Image resizing in Java using ImageKit.io
&lt;/h2&gt;

&lt;p&gt;We will learn the following image manipulation in Java using ImageKit.io. It doesn’t require you to install any third-party image processing library. You can scale from zero to millions of image requests per minute without having to worry about scaling or maintaining infrastructure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Basic image resizing, height and width manipulation&lt;/li&gt;
&lt;li&gt;  Cropping &amp;amp; preserving aspect ratio while resizing images&lt;/li&gt;
&lt;li&gt;  Add watermark in images&lt;/li&gt;
&lt;li&gt;  Adding text over images&lt;/li&gt;
&lt;li&gt;  Generating encrypted secured image URLs&lt;/li&gt;
&lt;li&gt;  Converting image format&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basic image resizing in Java
&lt;/h2&gt;

&lt;p&gt;You can manipulate the height and width of an image using simple URL parameters. Your backend can generate these URLs in Java or in the frontend itself.&lt;/p&gt;

&lt;p&gt;For example, the original image is 1280x853px.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uYnysCjc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/zJ2QcSvO.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uYnysCjc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/zJ2QcSvO.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Original 1280x853 image



&lt;p&gt;To get a 200px wide image, use &lt;code&gt;tr=w-200&lt;/code&gt; query parameter&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg?tr=w-200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GH68B9qJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/D-YMFvKL.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GH68B9qJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/D-YMFvKL.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
200px wide image



&lt;p&gt;To resize an image to 400 width and 200 height, you can use &lt;code&gt;tr=w-400,h-200&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg?tr=w-400,h-200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iMkmP1Ik--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/oycGsk2A.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iMkmP1Ik--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/oycGsk2A.jpeg" alt=""&gt;&lt;/a&gt;400x200 image&lt;/p&gt;

&lt;p&gt;Using &lt;a href="https://github.com/imagekit-developer/imagekit-java"&gt;ImageKit.io Java SDK&lt;/a&gt;, you can quickly generate image URLs like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;transformation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;();&lt;/span&gt;
&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"height"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"width"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;transformation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"urlEndpoint"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"/woman.jpg"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"transformation"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transformation&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImageKit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// https://ik.imagekit.io/ikmedia/tr:w-400,h-200/woman.jpg?ik-sdk-version=java-VERSION&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cropping &amp;amp; preserving aspect ratio while resizing images in Java
&lt;/h2&gt;

&lt;p&gt;If only one of the height(h) or width(w) is specified, then ImageKit.io adjusts the other dimension accordingly to preserve the aspect ratio, and no cropping occurs.&lt;/p&gt;

&lt;p&gt;But when you specify both height(h) and width(w) dimension and want to preserve the aspect ratio - you have the following three options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Crop some part of the image. You can choose which area to crop, where to focus etc.&lt;/li&gt;
&lt;li&gt;  Add padding around the image. You can control the background color of the padding to match the layout.&lt;/li&gt;
&lt;li&gt;  Let ImageKit change either height or width so that the whole image is visible. In this case, only one of the height or width matches the request dimension.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s understand different cropping options with examples.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No cropping, force-fit image in requested dimensions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you need an image in exact dimension as requested even if the aspect ratio is not preserved, use &lt;a href="https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#forced-crop-strategy-c-force"&gt;forced crop strategy&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg?tr=w-200,h-200,c-force
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--97h9Bc9D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/woman.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--97h9Bc9D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/woman.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Force fit



&lt;p&gt;&lt;strong&gt;Default center cropping&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you don’t choose any cropping strategy, ImageKit.io will crop the edges by default and show the center of the image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg?tr=w-200,h-200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L0uUwOOh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/center-cropping.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L0uUwOOh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/center-cropping.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Default center crop



&lt;p&gt;&lt;strong&gt;Fit inside the container (no cropping)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want the image to fit inside the container as per request height and width, use &lt;a href="https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#max-size-cropping-strategy-c-at_max"&gt;c-at_max&lt;/a&gt;. The full image content is preserved (no cropping), the aspect ratio is maintained, but the resulting height &amp;amp; width might differ from what is requested.&lt;/p&gt;

&lt;p&gt;The output image is less than or equal to the dimensions specified in the URL, i.e., at least one dimension will exactly match the output dimension requested, and the other dimension will be equal to or smaller than the corresponding output dimension requested.&lt;/p&gt;

&lt;p&gt;It is equivalent to &lt;code&gt;object-fit:contain&lt;/code&gt; or &lt;code&gt;background-size:contain&lt;/code&gt; CSS properties.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg?tr=w-400,h-200,c-at_max
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nOCW6pFD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/c-at_max.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nOCW6pFD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/c-at_max.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
300x200 image fits inside 400x200 container



&lt;p&gt;&lt;strong&gt;Fill container (no cropping)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want the image to cover the whole container as per the requested height and width, use &lt;a href="https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#min-size-cropping-strategy-c-at_least"&gt;c-at_least&lt;/a&gt;. The entire image content is preserved i.e. no cropping, the aspect ratio is maintained, but the resulting height &amp;amp; width might be different from what is requested.&lt;/p&gt;

&lt;p&gt;One of the dimensions will be the same as what is requested, while the other dimension will be equal to or larger than what is asked for.&lt;/p&gt;

&lt;p&gt;It is roughly equivalent to &lt;code&gt;object-fit:cover&lt;/code&gt; or &lt;code&gt;background-size:cover&lt;/code&gt; CSS properties.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg?tr=w-400,h-200,c-at_max&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3Yxcc7ne--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/c-at_least.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3Yxcc7ne--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/c-at_least.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
400x267 image covers 400x200 container



&lt;p&gt;&lt;strong&gt;No cropping, add padding around the image&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you don’t want the image to be cropped while maintaining the aspect ratio, you can add padding around the edges to get the desired dimension. You can also control the background color of this padding.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg?tr=w-200,h-100,cm-pad_resize,bg-DDDDDD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z6eQKTiB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/pad_resize.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z6eQKTiB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/pad_resize.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
200x100 image with padding



&lt;p&gt;&lt;strong&gt;Smart cropping&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ImageKit.io can intelligently crop image such that the object of interest remains in the center using &lt;a href="https://imagekit.io/blog/smart-crop-intelligent-image-cropping-imagekit/"&gt;smart cropping&lt;/a&gt;. In the thumbnail generated below, the woman is kept in the center.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg?tr=w-200,h-200,fo-auto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W2MDWYyR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/smart-crop.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W2MDWYyR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/smart-crop.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Smart crop



&lt;p&gt;&lt;strong&gt;Face cropping&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can crop and focus around the human face using the &lt;code&gt;fo-face&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NBzLffWN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/face-crop.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NBzLffWN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/face-crop.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Face crop



&lt;h2&gt;
  
  
  Add watermark in images in Java
&lt;/h2&gt;

&lt;p&gt;You can protect your images by adding your logo over them. If you try to achieve this in Java or using open-source image processing libraries, you will have to deal with low-level file operations and library-specific technicalities.&lt;/p&gt;

&lt;p&gt;With ImageKit, it is straightforward to add a watermark in images in Java. Let’s say we want to put our logo on an image.&lt;/p&gt;

&lt;p&gt;Logo can be accessed at -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/logo/light-icon_GTyhLlWNX-.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The image we want to watermark -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg?tr=w-600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;a href="https://docs.imagekit.io/features/image-transformations/overlay#overlay-image-oi"&gt;the overlay image (oi)&lt;/a&gt; transformation, we can generate a watermarked image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg?tr=oi-logo@@light-icon_GTyhLlWNX-.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TTfqg5mk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/watermarking-java.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TTfqg5mk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/watermarking-java.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Watermarked image



&lt;p&gt;You can also control the position, size, and other manipulation options of the overlay image. &lt;a href="https://docs.imagekit.io/features/image-transformations/overlay#image-overlay"&gt;Learn more&lt;/a&gt; about image overlay from the docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding text over images in Java
&lt;/h2&gt;

&lt;p&gt;You can add text over images in Java using ImageKit.io &lt;a href="https://docs.imagekit.io/features/image-transformations/overlay#text-overlay"&gt;text overlay&lt;/a&gt;. You can create engaging visuals in Java using URL-based parameters to add watermark and text on images dynamically.&lt;/p&gt;

&lt;p&gt;For example - We have added &lt;code&gt;ot-Sky is the limit&lt;/code&gt; in the URL to add a string “Sky is the limit” over the image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/backlit.jpg?tr=ot-Sky is the limit,otbg-FFFFFF90,otp-20,ots-70,otc-00000,ox-N0,oy-30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RLXMyHz3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/text-overlay.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RLXMyHz3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imagekit.io/blog/content/images/2020/12/text-overlay.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Text overlay



&lt;p&gt;You can generate photo collage in Java using the same methods. Learn more about &lt;a href="https://imagekit.io/blog/how-to-create-a-photo-collage/"&gt;how to create a photo collage&lt;/a&gt; using ImageKit.&lt;/p&gt;

&lt;p&gt;You can use &lt;a href="https://github.com/imagekit-developer/imagekit-java"&gt;Java SDK&lt;/a&gt; to simplify URL generation in your backend application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;transformation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;();&lt;/span&gt;
&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;overlay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;overlay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"overlay_text"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"Sky is the limit"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;overlay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"otbg"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"FFFFFF90"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;overlay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"otp"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"20"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;overlay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"overlay_text_font_size"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"70"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;overlay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"overlay_text_color"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"00000"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;overlay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"overlay_x"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"N0"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;overlay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"overlay_y"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"30"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;transformation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;overlay&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"urlEndpoint"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"/backlit.jpg"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"transformation"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transformation&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImageKit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// https://ik.imagekit.io/ikmedia/tr:ot-Sky is the limit,otbg-FFFFFF90,otp-20,ots-70,otc-00000,ox-N0,oy-30/woman.jpg?ik-sdk-version=java-VERSION&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generating encrypted secured image URLs in Java
&lt;/h2&gt;

&lt;p&gt;At times, you might want to secure access to your media assets to limit misuse. Or you might want to set a time-based expiry on the image URLs to make it hard for web scarpers to use your image URLs.&lt;/p&gt;

&lt;p&gt;To solve this, you can create signed image URLs in your backend application written in Java. A signed URL is a secure URL that can be generated only by you using your &lt;a href="https://docs.imagekit.io/api-reference/api-introduction/api-keys#private-key"&gt;account's private key&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For example, let’s create a signed URL that expires in 300 seconds with the default URL endpoint and other query parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;transformation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;();&lt;/span&gt;
&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"height"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"width"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;transformation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"/default-image.jpg"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"signed"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"expireSeconds"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImageKit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// https://ik.imagekit.io/your_imagekit_id/tr:h-600,w-400/default-image.jpg?ik-t=1567358667&amp;amp;ik-s=f2c7cdacbe7707b71a83d49cf1c6110e3d701054&amp;amp;ik-sdk-version=java-VERSION&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If someone tries to modify the image transformation or use it beyond its intended expiry time of 300 seconds, a &lt;code&gt;401 Unauthorised&lt;/code&gt; response is returned instead of the image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Converting image format in Java
&lt;/h2&gt;

&lt;p&gt;In Java, you can convert image format using &lt;code&gt;write()&lt;/code&gt; function provided by the class ImageIO under &lt;code&gt;javax.imageio&lt;/code&gt; package. The supported output formats are JPG, JPEG, PNG, BMP, WBMP, and GIF.&lt;/p&gt;

&lt;p&gt;However, you will have to deal with low-level file operations and image buffer. There is a different and easy way to convert image format in Java. Using an image CDN like ImageKit, you can easily &lt;a href="https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#format-f"&gt;convert image format&lt;/a&gt; using URL based transformation.&lt;/p&gt;

&lt;p&gt;For example - The actual format of the following image is JPG.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can convert it to PNG using &lt;code&gt;tr=f-png&lt;/code&gt; transformation.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg?tr=f-png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can covert it to WebP using &lt;code&gt;tr=f-webp&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://ik.imagekit.io/ikmedia/woman.jpg?tr=f-webp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;ImageKit also offers features such as &lt;a href="https://docs.imagekit.io/features/image-optimization/automatic-image-format-conversion"&gt;automatic best format selection&lt;/a&gt;, &lt;a href="https://docs.imagekit.io/features/image-optimization/quality-optimization"&gt;quality optimization&lt;/a&gt;, and &lt;a href="https://docs.imagekit.io/features/image-optimization/metadata-color-profile-and-orientation"&gt;metadata manipulation&lt;/a&gt; out of the box. This reduces the final size of the output image and improves your website's images load time while maintaining visual quality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;Here is what you need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If you only have a handful of images, use Java’s native image manipulation using the native Java ImageIO class.&lt;/li&gt;
&lt;li&gt;  If you need easy to use image resizing capabilities, go for a &lt;a href="https://imagekit.io/registration"&gt;free image CDN&lt;/a&gt; like ImageKit.io. With a forever free plan, you get 20GB of viewing bandwidth every month. It is sufficient for small scale businesses.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
    </item>
    <item>
      <title>Responsive Images - A Reference Guide from A to Z</title>
      <dc:creator>Manu Chaudhary</dc:creator>
      <pubDate>Tue, 24 Nov 2020 06:26:15 +0000</pubDate>
      <link>https://dev.to/manu4543/responsive-images-a-reference-guide-from-a-to-z-30aa</link>
      <guid>https://dev.to/manu4543/responsive-images-a-reference-guide-from-a-to-z-30aa</guid>
      <description>&lt;h2&gt;
  
  
  Chapter 1 - What is responsive images?
&lt;/h2&gt;

&lt;p&gt;In this guide, we will learn everything related to responsive images along with sample code. Basic knowledge of HTML and CSS is required to understand the concepts discussed here. After you finish reading, you will know the latest tools &amp;amp; techniques to implement responsive images correctly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Responsive images are the set of techniques used to load the right image based on device resolution, orientation, screen size, network connection, and page layout. The browser should not stretch the image to fit the page layout, and loading it shouldn’t result in time &amp;amp; bandwidth wastage. It improves user experience as images load fast and look crisp to the human eye.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Quick example of the responsive images in HTML
&lt;/h2&gt;

&lt;p&gt;The best way to understand responsive images is with a quick example. For simplicity, we will load a 2200px wide image on different devices. Everything else remains the same except the viewport size.&lt;/p&gt;

&lt;p&gt;The markup would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- The width of the orignal image is 2200px --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fdifferent-device-image-loading_0JWHR54wa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fdifferent-device-image-loading_0JWHR54wa.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For desktop (iMac), the image is optimal because the width of the viewport and image matches.&lt;/p&gt;

&lt;p&gt;However, in mobile, as we can see, the viewport is only 375 CSS pixels wide. The same is valid for the tablet. The viewport is only 1024 CSS pixels wide. We are wasting time and bandwidth downloading this overly large file.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s happening?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fresponsive-images-basic_-JpFBXzZ2.png%3Ftr%3Dw-1400%2Cf-png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fresponsive-images-basic_-JpFBXzZ2.png%3Ftr%3Dw-1400%2Cf-png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a simplified version of responsive images in action. 🙌&lt;/p&gt;

&lt;p&gt;We used &lt;code&gt;srcset&lt;/code&gt; (source set) to provide the browser with three different size images. The browser picked the right option based on the actual viewport size of the device. We will soon discover more about &lt;code&gt;srcset&lt;/code&gt; and other options in great detail.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that we are still using the old &lt;code&gt;src&lt;/code&gt; attribute as a fallback if the browser doesn’t support the &lt;code&gt;srcset&lt;/code&gt; attribute. As of Oct 2020, all browsers support &lt;code&gt;srcset&lt;/code&gt; except Opera mini and IE.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Chapter 2 - Why do we need responsive images?
&lt;/h2&gt;

&lt;p&gt;As you saw in the above example, one size doesn’t fit all. A responsive design should adapt based on user screen size, pixel density, and device orientation to ensure a great user experience.&lt;/p&gt;

&lt;p&gt;Here are three main reasons why we need to implement responsive images:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Render a high-quality image on different devices&lt;/li&gt;
&lt;li&gt;Loading the right image - Art direction&lt;/li&gt;
&lt;li&gt;Faster loading web pages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Render a high-quality image on different devices
&lt;/h2&gt;

&lt;p&gt;An image without perceptible artifacts looks crisp and contributes towards a great user experience. This is especially important on retail sites where users expect to view high-resolution closeups of product images to better look at texture &amp;amp; details. &lt;/p&gt;

&lt;p&gt;For an image to look good, it must adapt based on viewport width and screen pixel density. Let’s understand these:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Different viewport width case&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your layout changes based on the device viewport, the loaded image dimension should match the container CSS/HTML width. If the browser stretches a smaller image to fit the design, the rendered image will look blurred, and if you load a bigger image on a device with small viewport width, it results in bandwidth and time wastage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Different pixel density case&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;High-resolution displays have a higher pixel density. This means more pixels in the same amount of physical space. As a result, high-resolution displays demand images with more pixels. In simple terms, a large image is required to fit the same physical image.&lt;/p&gt;



&lt;p&gt;Consider an iPhone8:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSS viewport size: 375px by 667px
&lt;/li&gt;
&lt;li&gt;Pixel density: 2
&lt;/li&gt;
&lt;li&gt;Effective device resolution: 750px by 1334px&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It means if we want to render a 100 CSS pixels wide image, we will have to load a 200px wide image for it to look sharp.&lt;/p&gt;

&lt;p&gt;For a device with pixel density 3, we will have to load a 300px wide image.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;However, note that it does not always mean that we have to load a large file size. On a device, with DPR (device pixel ratio) 2, a 2x wide image with low-quality (50) will look better than a 1x wide image with high-quality(90). Despite being similar in terms of file-size, the 2x image will give a sharper appearance. You can &lt;a href="https://imagekit.io/how-to-show-high-quality-e-commerce-product-images/" rel="noopener noreferrer"&gt;learn more&lt;/a&gt; about this technique.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. Loading the right image - Art direction
&lt;/h2&gt;

&lt;p&gt;When a large image is resized to fit a small area, it can lose its relevance, usefulness, and legibility. The most important part might get cropped. &lt;/p&gt;

&lt;p&gt;For example, consider this screenshot of a dashboard on a product landing page. It is highlighting different elements of the user interface to a potential user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fscreenshot-desktop_T6JakuDWz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fscreenshot-desktop_T6JakuDWz.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the desktop, the above image is perfect. However, if we downscale the same image to fit a mobile viewport, we are losing many essential elements of the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fscreenshot-mobile_G_jAuf4fb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fscreenshot-mobile_G_jAuf4fb.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, an altogether different image might have been more appropriate, for example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fscreenshot-mobile-1_OukK3jT_X.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fscreenshot-mobile-1_OukK3jT_X.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is called &lt;strong&gt;art direction&lt;/strong&gt;. By "art directing", you can explicitly decide which image should be shown based on the image's size on the page. We will cover this technique in more detail soon.&lt;/p&gt;

&lt;p&gt;You can also use this to show different images in a mobile device based on orientation - landscape vs portrait mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Faster loading web pages
&lt;/h2&gt;

&lt;p&gt;According to the HTTP archive data, 64% of a website’s page weight, on an average, is made up of images. With mobile traffic surpassing desktop traffic, it has become even more crucial to optimize images for different device sizes.&lt;/p&gt;

&lt;p&gt;Ideally, you would like to serve images that are resized to match the user’s viewport dimensions. Without a means to do this, you will have to send an overly large image to all users. This means that the user on a mobile device with a small viewport width has to download that extra data, which slows down the page load. This is a wastage of time, bandwidth, and money and degrades the overall user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chapter 3 - How to make images responsive?
&lt;/h2&gt;

&lt;p&gt;There are many methods for implementing responsive images. We have come a long way from using hacky javascript based solutions to having native support in modern browsers.&lt;/p&gt;

&lt;p&gt;In this chapter, we will cover the latest methods for implementing responsive images.&lt;/p&gt;

&lt;p&gt;Let’s have a quick comparison before discussing each of these techniques in more details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Srcset&lt;/li&gt;
&lt;li&gt;Srcset with sizes&lt;/li&gt;
&lt;li&gt;Picture element&lt;/li&gt;
&lt;li&gt;Client-hints&lt;/li&gt;
&lt;li&gt;Responsive images in CSS&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;When to use&lt;/th&gt;
&lt;th&gt;Markup complexity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Using srcset&lt;/td&gt;
&lt;td&gt;For fixed-size images that take roughly whole viewport width, e.g., full-width promotional banner.&lt;/td&gt;
&lt;td&gt;Simple&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Using srcset + sizes&lt;/td&gt;
&lt;td&gt;For flexible images. When the layout &amp;amp; image size changes based on the viewport width. For e.g., a three-column layout on desktop vs a two-column layout on the mobile device.&lt;/td&gt;
&lt;td&gt;Slightly complex&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Using picture element&lt;/td&gt;
&lt;td&gt;When you want to load an entirely different image based on screen size i.e. &lt;strong&gt;art direction&lt;/strong&gt;. Or you want to use the latest image formats like &lt;code&gt;webp&lt;/code&gt; or &lt;code&gt;avif&lt;/code&gt; on a supported device.&lt;/td&gt;
&lt;td&gt;Highly complex.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Using client-hints&lt;/td&gt;
&lt;td&gt;When you don’t want to make major changes in the HTML markup.&lt;/td&gt;
&lt;td&gt;No major code change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Responsive images in CSS&lt;/td&gt;
&lt;td&gt;When you are loading images via CSS styles as a background image.&lt;/td&gt;
&lt;td&gt;Simple&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Chapter 4 - Srcset
&lt;/h2&gt;

&lt;p&gt;The standard &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag allows us to define a single image source. As a web developer, it becomes our responsibility to make sure that the right source is defined. But since we don’t have all the information about the device beforehand, it becomes tricky to create a bulletproof markup that loads optimal images for all resolutions.&lt;/p&gt;

&lt;p&gt;Remember the little conversation between a web developer and a browser?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fresponsive-images-basic_-JpFBXzZ2.png%3Ftr%3Dw-1400%2Cf-png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fresponsive-images-basic_-JpFBXzZ2.png%3Ftr%3Dw-1400%2Cf-png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;srcset&lt;/code&gt; allows you to define a list of different image resources along with size information so that browser can pick the most appropriate image based on the actual device’s resolution.&lt;/p&gt;

&lt;p&gt;Each comma-separated item in &lt;code&gt;srcset&lt;/code&gt; has:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Image URL, e.g. &lt;code&gt;http://ik.imagekit.io/demo/default-image.jpg&lt;/code&gt; or relative path &lt;code&gt;/demo/default-image.jpg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;An empty space&lt;/li&gt;
&lt;li&gt;The actual width of the image or display density:

&lt;ul&gt;
&lt;li&gt;Either using display density descriptor, for example, &lt;code&gt;1.5x&lt;/code&gt;, &lt;code&gt;2x&lt;/code&gt; etc.&lt;/li&gt;
&lt;li&gt;Or, using width descriptors, for example, &lt;code&gt;450w&lt;/code&gt;. This is the width of the image in pixels.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Using display density descriptor
&lt;/h2&gt;

&lt;p&gt;The syntax for display density descriptors is straightforward. &lt;code&gt;srcset&lt;/code&gt; provides a comma-separated list of image resources along with display density it should be used, for example&lt;code&gt;1x&lt;/code&gt;, &lt;code&gt;2x&lt;/code&gt; etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg"&lt;/span&gt; 
     &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg,
             image_2x.jpg 2x"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a display density descriptor isn’t provided, it is assumed to be &lt;code&gt;1x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo - srcset with density descriptor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s see this in action with a live demo - &lt;a href="https://imagekitio.github.io/responsive-images-guide/srcset-density.html" rel="noopener noreferrer"&gt;https://imagekitio.github.io/responsive-images-guide/srcset-density.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using &lt;a href="https://developers.google.com/web/tools/chrome-devtools/device-mode" rel="noopener noreferrer"&gt;device emulator&lt;/a&gt; in Chrome, at DPR 1, the image currentSrc is &lt;code&gt;https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-300&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fsrcset-density-demo_9xtjWY-J3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fsrcset-density-demo_9xtjWY-J3.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, if we consider different DPR values:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;DPR value&lt;/th&gt;
&lt;th&gt;Image picked by browser (currentSrc)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-300" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-300&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-600" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-600&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-900" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-900&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;When to use display density descriptors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use display density descriptors if your images are of fixed width, and the only thing that varies is display density. It is never that simple though 😉 &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenges in using display density descriptor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As per pixensity.com, there are more than 300 different types of phones, tablets, laptops, and desktop devices with varying screen sizes and display density. &lt;/p&gt;

&lt;p&gt;The critical question becomes, do you want to track different display densities available, for example, 1x, 1.5x, 2x, 2.5x, 3x 4x, etc. More often, you will need to go beyond taking care of display density, so this method won’t be sufficient. &lt;/p&gt;

&lt;h2&gt;
  
  
  Using width descriptor
&lt;/h2&gt;

&lt;p&gt;The syntax is similar to the display density descriptor, but instead of display density values, we provide the actual width of the image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg"&lt;/span&gt; 
     &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"small.jpg 300w,
             medium.jpg 600w,
             large.jpg 900w"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This lets the browser pick the best image&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using width descriptor allows the browser to pick the best candidate from &lt;code&gt;srcset&lt;/code&gt; based on the actual width needed to render that image on that particular display at runtime. &lt;/p&gt;

&lt;p&gt;Note that display pixel density is also taken into account by the browser while calculating the required width. 😎&lt;/p&gt;

&lt;p&gt;For example, assuming an image takes up the whole viewport width - On a 300px wide screen with DPR 2, the browser will pick &lt;code&gt;medium.jpg&lt;/code&gt; because it needs a 300x2=600px wide image. On a 300px wide screen with DPR value 3, the browser will select &lt;code&gt;large.jpg&lt;/code&gt; because it needs a 300x3=900px wide image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo - srcset with width descriptor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let see this in action with a live demo - &lt;a href="https://imagekitio.github.io/responsive-images-guide/srcset-width.html" rel="noopener noreferrer"&gt;https://imagekitio.github.io/responsive-images-guide/srcset-width.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using the device emulator, let’s resize the screen to 250px and set DPR at 1. The image loaded in this case is &lt;code&gt;https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-300&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fsrcset-width-descriptor-demo_4T81jNSqR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fsrcset-width-descriptor-demo_4T81jNSqR.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, if we consider combinations with different viewport width and DPR values:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Viewport width&lt;/th&gt;
&lt;th&gt;DPR value&lt;/th&gt;
&lt;th&gt;Final width of the image required (width × DPR)&lt;/th&gt;
&lt;th&gt;Image picked by the browser (currentSrc)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;250px&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;250 × 1 = 250px&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-300" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-300&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;250px&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;250 × 2 = 500px&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-600" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-600&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;250px&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;250 × 3 = 750px&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-900" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-900&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;300px&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;300 × 1 = 300px&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-300" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-300&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;300px&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;300 × 2 = 600px&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-600" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-600&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;300px&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;300 × 3 = 900px&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-900" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/paddy.jpg?tr=w-900&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice how the browser is taking display density and viewport width into account while calculating the required image's final width.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges with using only srcset
&lt;/h2&gt;

&lt;p&gt;If you are loading a fixed-width image that will take up almost full viewport width, then use &lt;code&gt;srcset&lt;/code&gt; along with width descriptors.&lt;/p&gt;

&lt;p&gt;However, in the below cases using &lt;code&gt;srcset&lt;/code&gt; alone won’t be sufficient:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you are loading flexible images i.e. when the size of your image changes based on the size of the viewport. For example, a single-column layout on the mobile and a three-column layout on desktop devices will need different dize images.&lt;/li&gt;
&lt;li&gt;Or when the image is only taking a fraction of viewport width. Since the browser is not aware of the layout, it will assume the image will take up the whole viewport width and download a much bigger image than required.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wait. What? The browser is not aware of the layout!&lt;/p&gt;

&lt;p&gt;It is logical to think that browser has stylesheets to find our required size of the image element but note that those stylesheets are not parsed yet. If the browser waits till all stylesheets are parsed &amp;amp; executed, it will inevitably delay the downloading of images.&lt;/p&gt;

&lt;p&gt;To understand this better, let’s first look at how the browser loads a page.&lt;/p&gt;

&lt;h3&gt;
  
  
  How browser loads a webpage — the old way
&lt;/h3&gt;

&lt;p&gt;A web page is made up of text, CSS, JS, and fonts. A lot happens in the background once you hit enter, and a page is finally rendered on your screen.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, the HTML is downloaded, and the browser starts parsing it. If it comes across an external style sheet, it starts downloading it in parallel and continue parsing HTML.&lt;/li&gt;
&lt;li&gt;If it comes across an inline &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags, it pauses the HTML parsing and executes the script right away.&lt;/li&gt;
&lt;li&gt;If it comes across a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag (one without &lt;code&gt;defer&lt;/code&gt; or &lt;code&gt;async&lt;/code&gt; attribute) that points to an external URL, it pauses the HTML parsing and first download and executes that Javascript resource.&lt;/li&gt;
&lt;li&gt;If it comes across an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag, it starts downloading the image resource in parallel and continues parsing HTML.&lt;/li&gt;
&lt;li&gt;Once all blocking external style sheets and Javascript is downloaded, parsed, and executed, the page is rendered.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if we have a HTML like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"vendor.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"app.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"zoom.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image1.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image2.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;– the browser loads resources like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fguides%2Fsequential-loading_YL1vzHxKJB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fguides%2Fsequential-loading_YL1vzHxKJB.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pausing the parser whenever a script is encountered results in sub-optimal use of the browser’s ability to download multiple external resources over the network in parallel. This method is delaying the download of resources required to render the page.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Pre-loaders or speculative parsing to rescue - the new way
&lt;/h3&gt;

&lt;p&gt;Internet Explorer, WebKit, and Mozilla all implemented pre-loaders in 2008 to improve the low network utilization problem that we just discussed. &lt;/p&gt;

&lt;p&gt;Essentially, the idea is that the browser cannot build DOM while executing a script but can still parse the rest of the markup looking for other resources, for example, stylesheets, javascript files, or images that are linked. These files are added to a list and start downloading in the background. By the time all scripts execute and HTML parsing finishes, hopefully, the browser has already downloaded these resources, and there won’t be any further delay.&lt;/p&gt;

&lt;p&gt;The waterfall chart for the example above now looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fguides%2Fparallel-download_mNDsx1fm-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fguides%2Fparallel-download_mNDsx1fm-.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we understand why &lt;code&gt;srcset&lt;/code&gt; alone is not sufficient for the browser to understand the image's required size. To overcome this problem, we have the &lt;code&gt;sizes&lt;/code&gt; attribute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chapter 5 - Srcset with sizes
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;sizes&lt;/code&gt; attribute contains a comma-separated list. Each item in the list describes the size of the image in relation to the viewport.&lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;sizes&lt;/code&gt; attribute with &lt;code&gt;srcset&lt;/code&gt; provides the browser with enough information to start downloading the right image as soon as it sees an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag in HTML without waiting for styles sheets to complete downloading and parsing. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why do we need sizes?&lt;/strong&gt;&lt;br&gt;
If you scrolled here directly and wondering why the browser is not aware of how big the image will render, checkout how the browser loads a web page.&lt;/p&gt;

&lt;p&gt;The syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg"&lt;/span&gt; 
     &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"small.jpg 300w,
             medium.jpg 600w,
             large.jpg 900w"&lt;/span&gt;
     &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 300px) 100vw, (max-width: 600px) 50vw, (max-width: 900px) 33vw, 900px"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each comma-separated item in &lt;code&gt;sizes&lt;/code&gt; has:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Media conditions, for example, &lt;code&gt;(max-width: 300px)&lt;/code&gt; - It describes a possible state that the screen can be in. &lt;code&gt;(max-width: 300px)&lt;/code&gt; means when the viewport width is 300 CSS pixels or less. It is similar to media queries but with some limitations. You cannot use &lt;code&gt;screen&lt;/code&gt; or &lt;code&gt;print&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;An empty space.&lt;/li&gt;
&lt;li&gt;The width of the image element when the media condition is true. You can provide an absolute length (px, em) or a length relative to the viewport (vw), but not percentages.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Demo - srcset with sizes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s see this in action with a live demo - &lt;a href="https://imagekitio.github.io/responsive-images-guide/srcset-sizes.html" rel="noopener noreferrer"&gt;https://imagekitio.github.io/responsive-images-guide/srcset-sizes.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fsrcset-sizes-demo_AGqVFPTap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fsrcset-sizes-demo_AGqVFPTap.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The layout is such that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If viewport width is above 900px, each image takes a fix 225px width.&lt;/li&gt;
&lt;li&gt;Upto 900px, each image takes up 33vw i.e. 33% width of total viewport width.&lt;/li&gt;
&lt;li&gt;Upto 700px, each image takes up 50vw i.e. 50% width of total viewport width.&lt;/li&gt;
&lt;li&gt;Upto 400px, each image takes up 100vw i.e. the whole viewport width.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HTML markup of a single image element looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/women-dress-1.jpg"&lt;/span&gt; 
     &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-225 225w,
             https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-300 300w,
             https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-350 350w,
             https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-640 640w"&lt;/span&gt;
     &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 400px) 100vw, (max-width: 700px) 50vw, (max-width: 900px) 33vw, 225px"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s see what happens at different screen size and DPR values -&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Viewport width&lt;/th&gt;
&lt;th&gt;DPR value&lt;/th&gt;
&lt;th&gt;Image size required (width × DPR)&lt;/th&gt;
&lt;th&gt;Image picked by the browser (currentSrc)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;350px&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;100vw i.e. 350 × 1 = 350px&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-350" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-350&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;350px&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;100vw i.e. 350 × 2 = 700px&lt;/td&gt;
&lt;td&gt;Closest candidate is &lt;a href="https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-640" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-640&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;650px&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;50vw i.e. (650/2) × 1 = 325px&lt;/td&gt;
&lt;td&gt;Closest candidate is&lt;br&gt;&lt;a href="https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-350" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-350&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1024px&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;225 × 1 = 225px&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-225" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-225&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1024px&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;225 × 2 = 450px&lt;/td&gt;
&lt;td&gt;Closest candidate is &lt;br&gt;&lt;a href="https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-350" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-350&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How to choose breakpoints for srcset and define sizes?
&lt;/h2&gt;

&lt;p&gt;When implementing responsive images, you will have to write the values for the &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt; attributes. It can quickly get tricky. So let’s repeat the purpose of these two attributes so that it becomes easy to derive the values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;srcset&lt;/code&gt; - To define multiple image sources of different widths and let the browser pick the most appropriate candidate during HTML parsing.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sizes&lt;/code&gt; - To define the size of the image element. It could be a fixed size like &lt;code&gt;225px&lt;/code&gt; or relative to the viewport. You can use CSS media conditions here to provide different size values based on the viewport width.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before you provide different image sources in  &lt;code&gt;srcset&lt;/code&gt;, you need to understand what all sizes do you need based on the layout. It is going to be site-specific, meaning it is closely tied to your CSS.&lt;/p&gt;

&lt;p&gt;Here is a simple approach to this problem.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;While calculating sizes, think in terms of image width relative to the viewport. For example - “My layout is such that my image is going to be roughly X percent of the viewport if the screen size is above Y px.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s understand this with a few examples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;sizes="(min-width 1024px) 33vw, 95vw)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It means - “The image is in a three-column layout on a screen larger than 1024px. Otherwise, it is close to full viewport width leaving some space around it”.&lt;/p&gt;

&lt;p&gt;Now, let’s pick the &lt;code&gt;sizes&lt;/code&gt; from our demo - &lt;a href="https://imagekitio.github.io/responsive-images-guide/srcset-sizes.html" rel="noopener noreferrer"&gt;https://imagekitio.github.io/responsive-images-guide/srcset-sizes.html&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;sizes="(max-width: 400px) 100vw, (max-width: 700px) 50vw, (max-width: 900px) 33vw, 225px"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It means - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If viewport width is upto 400px, each image takes up 100vw i.e. the whole viewport width.&lt;/li&gt;
&lt;li&gt;Upto 700px, each image takes up 50vw i.e. 50% width of total viewport width.&lt;/li&gt;
&lt;li&gt;Upto 900px, each image takes up 33vw i.e. 33% width of total viewport width.&lt;/li&gt;
&lt;li&gt;Above 900px, each image takes a fix 225px width.
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Defining image width relative to viewport does not always provide the most optimal image considering many devices &amp;amp; corresponding viewport width &amp;amp; DPR values. However, it is a practical solution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once we know the value of &lt;code&gt;sizes&lt;/code&gt;, it is easy to find out what all different size images we need to define in &lt;code&gt;srcset&lt;/code&gt; - &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Image size candidates from sizes&lt;/th&gt;
&lt;th&gt;Effective size at different DPR values&lt;br&gt;(width × DPR)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;400px&lt;br&gt;From the first media condition i.e.&lt;br&gt;&lt;code&gt;max-width: 400px) 100vw&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;400px at 1x&lt;br&gt;800px at 2x&lt;br&gt;1200px at 3x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;350px&lt;br&gt;From the second media condition i.e.&lt;br&gt;&lt;code&gt;(max-width: 700px) 50vw&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;350px at 1x&lt;br&gt;700px at 2x&lt;br&gt;1025px at 3x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;300px&lt;br&gt;From the third media condition i.e.&lt;br&gt;&lt;code&gt;max-width: 900px) 33vw&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;300px at 1x&lt;br&gt;600px at 2x&lt;br&gt;900px at 3x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;225px&lt;br&gt;From the fourth default media condition i.e. &lt;br&gt;&lt;code&gt;225px&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;225px at 1x&lt;br&gt;450px at 2x&lt;br&gt;675px at 3x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you sort the effective sizes, here is what you will get - &lt;/p&gt;

&lt;p&gt;&lt;code&gt;225px&lt;/code&gt;, &lt;code&gt;300px&lt;/code&gt;,  &lt;code&gt;350px&lt;/code&gt;, &lt;code&gt;400px&lt;/code&gt;, &lt;code&gt;450px&lt;/code&gt;, &lt;code&gt;600px&lt;/code&gt;, &lt;code&gt;675px&lt;/code&gt;, &lt;code&gt;700px&lt;/code&gt;, &lt;code&gt;800px&lt;/code&gt;, &lt;code&gt;900px&lt;/code&gt;, &lt;code&gt;1025px&lt;/code&gt; and &lt;code&gt;1200px&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you are using an image CDN like ImageKit.io, it is easy to provide images in different dimension by addign URL parameters e.g.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;225px&lt;/code&gt; wide image - &lt;a href="https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-225" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-225&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;300px&lt;/code&gt; wide image - &lt;a href="https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-300" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-300&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;600px&lt;/code&gt; wide image - &lt;a href="https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-600" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-600&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, you don’t have to provide images at all required sizes in &lt;code&gt;srcset&lt;/code&gt;. You can select a few candidates, and the browser will pick the closest one. This serves two purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You don’t have to generate and store multiple variants of the same image.&lt;/li&gt;
&lt;li&gt;If you are using a CDN for faster delivery and caching, then having a few variants will improve your cache hit ratio as the repeat request will increase.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So you can pick three or four candidates and write  &lt;code&gt;srcset&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;srcset="https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-225 225w,
        https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-350 350w,
        https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-700 700w,
        https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-900 900w"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tips for choosing breakpoints while writing srcset
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You can look at your Google analytics device report to see what screen resolutions you should care about most. Accordingly, you will know which layout needs the most optimization. For example, assuming that 60% of the users on your website see a three-column layout and 20% see a single column layout. Then you can consider all size variations you need for these two layouts at multiple DPR values and write &lt;code&gt;srcset&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;To increase cache hit ratio on CDN, don’t try and provide &lt;code&gt;srcset&lt;/code&gt; for all possible breakpoints and sizes. CDN cannot cache all your resources. Some resources have to evict to make space for others. This would cause more performance bottlenecks than gains.&lt;/li&gt;
&lt;li&gt;When in doubt - First think about your layout, i.e. CSS  ➡️ , then accordingly write  &lt;code&gt;sizes&lt;/code&gt;  ➡️ And finally choose breakpoints for  &lt;code&gt;srcset&lt;/code&gt; considering different DPR values and effective image sizes you need 🙌.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Chapter 6 - Using picture element
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt; are useful to define multiple dimension variants of the same image. But if you need art direction - that is, to explicitly dictate browser to load an entirely different image based on browser viewport or image format support, you need &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use the Picture element
&lt;/h2&gt;

&lt;p&gt;Picture element should be used to achieve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Art direction&lt;/li&gt;
&lt;li&gt;Different format support&lt;/li&gt;
&lt;li&gt;Color theme example&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/large.jpg"&lt;/span&gt;
          &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 800px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/small.jpg"&lt;/span&gt;
          &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 400px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/large.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element consists of zero or more  &lt;code&gt;source&lt;/code&gt; and one &lt;code&gt;img&lt;/code&gt; element. The browser will consider each &lt;code&gt;source&lt;/code&gt; element to choose the best match based on device display and image format support.&lt;/p&gt;

&lt;p&gt;Each &lt;code&gt;source&lt;/code&gt; accepts &lt;code&gt;media&lt;/code&gt; and &lt;code&gt;type&lt;/code&gt; attributes in addition to well known &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Media attribute
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;media&lt;/code&gt; attribute contains a media condition like CSS media query. If a source’s element media condition evaluates to &lt;code&gt;false&lt;/code&gt;, the browser skips that source. If none of the source element’s media conditions evaluate to &lt;code&gt;true&lt;/code&gt;, the browser loads the image specified in the &lt;code&gt;img&lt;/code&gt; tag.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example - Loading different based on screen size
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/large.jpg"&lt;/span&gt;
          &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 800px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/small.jpg"&lt;/span&gt;
          &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 400px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/large.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser will pick one of the source elements based on the &lt;code&gt;media&lt;/code&gt; condition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Srcset attribute
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;srcset&lt;/code&gt; attribute is the same as we discussed before. It contains a comma-separated list of different image resources.&lt;/p&gt;

&lt;p&gt;Each comma-separated item in &lt;code&gt;srcset&lt;/code&gt; has:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Image URL, e.g. &lt;code&gt;http://ik.imagekit.io/demo/default-image.jpg&lt;/code&gt; or relative path &lt;code&gt;/demo/default-image.jpg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;An empty space&lt;/li&gt;
&lt;li&gt;The real width of the image:

&lt;ul&gt;
&lt;li&gt;Either using display density descriptor e.g. &lt;code&gt;1.5x&lt;/code&gt;, &lt;code&gt;2x&lt;/code&gt; etc.&lt;/li&gt;
&lt;li&gt;Or, using width descriptors e.g. &lt;code&gt;450w&lt;/code&gt;. This is the width of the image in pixels.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example - Loading different based on device pixel ratio
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"large_1x.jpg 1x, large_2x.jpg 2x, large_3x.jpg 3x"&lt;/span&gt;
          &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 800px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"small_1x.jpg 1x, small_2x.jpg 2x, small_1x.jpg 3x"&lt;/span&gt;
          &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 400px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"large_3x.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Type attribute
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;type&lt;/code&gt; attribute specified the MIME type of the resource URL(s) in the source’s &lt;code&gt;srcset&lt;/code&gt;. If the browser supports that MIME type, it will load the resource. Otherwise, it will skip that source and move to the next. If none of the source’s type is supported by the browser, the image in &lt;code&gt;img&lt;/code&gt; is loaded.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example - Loading different image format based on browser support
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/image.webp"&lt;/span&gt;
          &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/image.avif"&lt;/span&gt;
          &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/avif"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/image.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Live demo of using the picture element
&lt;/h2&gt;

&lt;p&gt;Let’s see this in action with a live demo - &lt;a href="https://imagekitio.github.io/responsive-images-guide/picture.html" rel="noopener noreferrer"&gt;https://imagekitio.github.io/responsive-images-guide/picture.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fpicture-element-demo_U9wD8pBJV.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fpicture-element-demo_U9wD8pBJV.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; elements in this demo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first example contains a screenshot of the ImageKit media library to showcase different user interface elements. The interface varies based on screen size. So to depict the same, we are loading a different screenshot based on screen size. For screen size greater than or equal to &lt;code&gt;800px&lt;/code&gt;, you will see a desktop version of the user interface i.e. &lt;a href="https://ik.imagekit.io/ikmedia/dashboard.png" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/dashboard.png&lt;/a&gt;. Otherwise, you will see a mobile-friendly version i.e. &lt;a href="https://ik.imagekit.io/ikmedia/dashboard-mobile.png" rel="noopener noreferrer"&gt;https://ik.imagekit.io/ikmedia/dashboard-mobile.png&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The second example demonstrates loading a WebP format image if the browser has support for it. Otherwise, a JPG image is loaded.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Loading different image in dark mode vs light mode
&lt;/h2&gt;

&lt;p&gt;Dark mode lets you change the background color of an app window to black. As a web developer, you can choose to load a different image if a user has turned on dark mode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"dark.jpg"&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(prefers-color-scheme: dark)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"light.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser will evaluate the media condition &lt;code&gt;(prefers-color-scheme: dark)&lt;/code&gt;, and if it is &lt;code&gt;true&lt;/code&gt;, it will pick that source and load &lt;code&gt;dark.jpg&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is how it looks, toggle the dark mode setting and refresh the page to see how the browser loads a different image.&lt;/p&gt;

&lt;p&gt;Live demo - &lt;a href="https://imagekitio.github.io/responsive-images-guide/dark-vs-light-mode.html" rel="noopener noreferrer"&gt;https://imagekitio.github.io/responsive-images-guide/dark-vs-light-mode.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fguides%2Flight-vs-dark-mode-demo_ngxfbrNyG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fguides%2Flight-vs-dark-mode-demo_ngxfbrNyG.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Chapter 7 - Using client hints
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What are client hints?
&lt;/h2&gt;

&lt;p&gt;As the name suggests, client hints are the hints provided by the client device to the server along with the request itself. These hints allow the server to fulfill a particular request with the most optimal resource. The latter is known as content negotiation.&lt;/p&gt;

&lt;p&gt;Client hints provide this information via HTTP request headers. For example - &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fdemo%2Fimagekitwebsite%2Ftr%3Af-png%2Fwp-content%2Fuploads%2Fdpr_request_header.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fdemo%2Fimagekitwebsite%2Ftr%3Af-png%2Fwp-content%2Fuploads%2Fdpr_request_header.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to enable client hints?
&lt;/h2&gt;

&lt;p&gt;Not every request has these HTTP headers. You will have to explicitly tell the browser to include these client hints using a &lt;code&gt;meta&lt;/code&gt; tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Accept-CH"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"DPR, Viewport-Width"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the browser to send the &lt;code&gt;DPR&lt;/code&gt; value (device pixel ratio) and &lt;code&gt;Viewport-Width&lt;/code&gt; (device screen width in CSS pixels) along with image requests.&lt;/p&gt;

&lt;p&gt;That’s great. But why do we need client hints in implementing responsive images when we already have &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;picture&lt;/code&gt;?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we need client hints?
&lt;/h2&gt;

&lt;p&gt;To understand the need for client hints, let's take a closer look at what we have learned so far -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt; to define URLs of different image variants and specify rendered image size so that browser can download the most appropriate image based on the size of the viewport on its own.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;picture&lt;/code&gt; element to dedicate how the browser should load a differently cropped or entirely different image, which is better suited for a smaller display.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;picture&lt;/code&gt; provides us with everything we need to implement responsive images use-cases, but it could be time-consuming to develop and maintain for complex use cases.&lt;/p&gt;

&lt;p&gt;All of the above methods require you to modify markup so that as a web developer, you can pass the essential missing piece of information that the browser needs at runtime to be able to download the right image. Well, client-hints do the same but without the complex markup — they provide the missing link between the browser and the server when it comes to layout information and device capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s understand with an example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose you have a simple resolution switching use cases where you want to load a different size variant of the same image based on the viewport width. The syntax would be -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg"&lt;/span&gt; 
     &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"small.jpg 300w,
             medium.jpg 600w,
             large.jpg 900w"&lt;/span&gt;
     &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 300px) 100vw, (max-width: 600px) 50vw, (max-width: 900px) 33vw, 225px"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, if you want to load a WebP image in a supported browser, your syntax becomes -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- webp format for (max-width: 300px) 100vw --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 300px) 100vw"&lt;/span&gt;
          &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"small.webp 300w,
                  medium.webp 600w,
                  large.webp 900w"&lt;/span&gt;
            &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- jpg format for (max-width: 300px) 100vw --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 300px) 100vw"&lt;/span&gt;
          &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"small.jpg 300w,
                  medium.jpg 600w,
                  large.jpg 900w"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/image.avif"&lt;/span&gt;
            &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/avif"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- webp format for (max-width: 600px) 50vw --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 300px) 100vw"&lt;/span&gt;
          &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"small.webp 300w,
                  medium.webp 600w,
                  large.webp 900w"&lt;/span&gt;
            &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- jpg format for (max-width: 600px) 50vw --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 300px) 100vw"&lt;/span&gt;
          &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"small.jpg 300w,
                  medium.jpg 600w,
                  large.jpg 900w"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/image.avif"&lt;/span&gt;
            &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/avif"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- webp format for (max-width: 900px) 33vw --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 300px) 100vw"&lt;/span&gt;
          &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"small.webp 300w,
                  medium.webp 600w,
                  large.webp 900w"&lt;/span&gt;
            &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- jpg format for (max-width: 900px) 33vw --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 300px) 100vw"&lt;/span&gt;
          &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"small.jpg 300w,
                  medium.jpg 600w,
                  large.jpg 900w"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"large.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes! It quickly gets complex.&lt;/p&gt;

&lt;p&gt;If we use client hints, the above syntax can be reduced to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Accept-CH"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"DPR, Width"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/image.jpg"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 300px) 100vw, (max-width: 600px) 50vw, (max-width: 900px) 33vw, 225px"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty amazing, right! No &lt;code&gt;srcset&lt;/code&gt;. But for this to work, the server should be capable of understanding client hints and respond appropriately.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We will discuss in detail how this is possible, but the bottom line is — when possible, you should aim to centralize image resizing &amp;amp; processing and automate as much as possible. This is precisely what client-hints do. ImageKit supports client hints out of the box.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Client hints for responsive images
&lt;/h2&gt;

&lt;p&gt;Among others, one of the primary uses of client hints is to send information about the required size of the image in the current page layout. This simplifies the markup and automates a lot of information passing from browser to web server when implementing responsive images. &lt;/p&gt;

&lt;p&gt;Let’s put that in perspective by taking a closer look at what all information does the browser need at runtime to be able to load an appropriate image -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Viewport width.&lt;/li&gt;
&lt;li&gt;How big will the image render? It depends upon your layout, which might adapt based on the width of the viewport.&lt;/li&gt;
&lt;li&gt;Device pixel ratio i.e. &lt;code&gt;1x&lt;/code&gt;, &lt;code&gt;2x&lt;/code&gt;, &lt;code&gt;3x&lt;/code&gt; or &lt;code&gt;4x&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;URL of the image resource for different sizes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can opt-in the following client hints, which will be sent as request headers along with HTTP request - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Width&lt;/code&gt; - Final size of the required image in page layout considering device pixel ratio&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DPR&lt;/code&gt; - Device pixel ratio&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Viewport-Width&lt;/code&gt; - Viewport width in CSS pixels.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Accept&lt;/code&gt; - This header is always sent with every request by default.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Save-Data&lt;/code&gt; - &lt;code&gt;on&lt;/code&gt; or &lt;code&gt;off&lt;/code&gt; to indicate the user’s preference to receive less data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ECT&lt;/code&gt; - &lt;em&gt;Effective Connection Type&lt;/em&gt; e.g. **&lt;code&gt;4g&lt;/code&gt;, &lt;code&gt;3g&lt;/code&gt;, &lt;code&gt;2g&lt;/code&gt;, and &lt;code&gt;slow-2g&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RTT&lt;/code&gt; - &lt;em&gt;Round Trip Time&lt;/em&gt;, in milliseconds, on the application layer.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Downlink&lt;/code&gt; - Approximate downstream speed of the user’s connection in megabits per second (Mbps).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;Width&lt;/code&gt;,  &lt;code&gt;DPR&lt;/code&gt;, and &lt;code&gt;Viewport-Width&lt;/code&gt; hints are most relevant to responsive images implementation as they allow the webserver to control the image size from the backend.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Accept&lt;/code&gt; hint can be used by the server to deliver images in next-generation format e.g. WebP or AVIF, without changing the image source URL or using the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element.&lt;/p&gt;

&lt;p&gt;The server can use network hints such as &lt;code&gt;Save-Data&lt;/code&gt;, &lt;code&gt;ECT&lt;/code&gt;, &lt;code&gt;RTT&lt;/code&gt;, and &lt;code&gt;Downlink&lt;/code&gt; to deliver a low-quality variant of the image, which will consume less data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Width
&lt;/h3&gt;

&lt;p&gt;It provides the final size of the image required as per page layout after factoring in the device pixel ratio.  &lt;code&gt;Width&lt;/code&gt;  hint is sent with requests for image resources fired off by &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt; tags using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-sizes" rel="noopener noreferrer"&gt;&lt;code&gt;sizes&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is the most useful client hint with respect to implementing responsive images. &lt;/p&gt;

&lt;p&gt;For example - Let’s say a page has an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element with the &lt;code&gt;sizes&lt;/code&gt; attribute set to 300. This means the layout needs a &lt;code&gt;300&lt;/code&gt; CSS pixel wide image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Allow Width header to be sent --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Accept-CH"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Width"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/image.jpg"&lt;/span&gt;&lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"300px"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the browser takes 300 and multiplies it with the device pixel ratio. Assuming device pixel ratio (DPR) is 2, browser sets &lt;code&gt;Width&lt;/code&gt; hint to &lt;code&gt;600,&lt;/code&gt; i.e. 300x2. This is the actual size of the image required for the current layout.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request headers
GET: /image.jpg
width: 600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the server to respond with an image, which is optimal for this device and the page's current layout.&lt;/p&gt;

&lt;h3&gt;
  
  
  DPR
&lt;/h3&gt;

&lt;p&gt;This hint provides the device pixel ratio. It is equivalent to &lt;code&gt;window.devicePixelRatio&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example - when opted in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Allow DPR header to be sent --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Accept-CH"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"DPR"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/image.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assuming, device pixel ratio is 2, the browser will set the &lt;code&gt;DPR&lt;/code&gt; hint to 2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request headers
GET: /image.jpg
dpr: 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use this header on the server to send the right image variant e.g. &lt;code&gt;1x&lt;/code&gt;, &lt;code&gt;2x&lt;/code&gt; or &lt;code&gt;3x&lt;/code&gt; based on the actual device pixel ratio.&lt;/p&gt;

&lt;h3&gt;
  
  
  Viewport-Width
&lt;/h3&gt;

&lt;p&gt;This hint provides the viewport width in CSS pixels. It is equivalent to &lt;code&gt;window.innerWidth&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;You can use this hint on the server-side to respond with an image that is suitable for a specific screen size. This is useful for implementing an art direction use-case.&lt;/p&gt;

&lt;p&gt;For example - when opted in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Allow Viewport-Width header to be sent --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Accept-CH"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Viewport-Width"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/image.jpg"&lt;/span&gt;&lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"300px"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assuming, device screen width is 300 CSS pixel wide, the browser will set &lt;code&gt;Viewport-Width&lt;/code&gt; hint to 300.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request headers
GET: /image.jpg
viewport-width: 300
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Accept
&lt;/h3&gt;

&lt;p&gt;It provides what all content type the browser supports, which can be leveraged by the server to send the most optimal response.&lt;/p&gt;

&lt;p&gt;Example use case includes serving images in WebP or AVIF format when browser declares the support for it in &lt;code&gt;Accept&lt;/code&gt; header. For example - &lt;code&gt;Accept&lt;/code&gt; header value in an image resource request in Chrome is &lt;code&gt;image/avif,image/webp,image/apng,image/*,*/*;q=0.8&lt;/code&gt;. It has &lt;code&gt;image/webp&lt;/code&gt; in it, and the server can use this to respond with WebP format.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Faccept-client-hint_GDvo26k8y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Faccept-client-hint_GDvo26k8y.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are using ImageKit, then it &lt;a href="https://docs.imagekit.io/features/image-optimization/automatic-image-format-conversion" rel="noopener noreferrer"&gt;automatically converts image format&lt;/a&gt; based on Accept header value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Save-Data
&lt;/h3&gt;

&lt;p&gt;This hint indicates the client's preference for reduced data usage. When the value is &lt;code&gt;on&lt;/code&gt;, the server should try to send an alternative smaller payload in the response. For example, in image requests, the server should respond with a lower quality image to reduce data usage if the value of &lt;code&gt;Save-Data&lt;/code&gt; request header is &lt;code&gt;on&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fdemo%2Fimagekitwebsite%2Ftr%3Aw-700%2Cdpr-2%2Cf-png%2Fwp-content%2Fuploads%2Fsave-data-header.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fdemo%2Fimagekitwebsite%2Ftr%3Aw-700%2Cdpr-2%2Cf-png%2Fwp-content%2Fuploads%2Fsave-data-header.jpg" alt="Save-Data Client Hint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mobile browsers such as Chrome Mobile and Opera Mobile allow the user to activate a data saver mode. With this mode enabled, the browsers send the &lt;code&gt;Save-Data&lt;/code&gt; header with the request, with the &lt;code&gt;on&lt;/code&gt; value. With this mode disabled, the &lt;code&gt;Save-Data&lt;/code&gt; header is not sent at all.&lt;/p&gt;

&lt;p&gt;For example, the right image is almost 33% smaller when accessed by a client with Save-Data enabled. You can test this on the Chrome desktop by installing &lt;a href="https://chrome.google.com/webstore/detail/data-saver/pfmgfdlgomnbgkofeojodiodmgpgmkac?hl=en" rel="noopener noreferrer"&gt;this extension&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fdemo%2Fimagekitwebsite%2Ftr%3Aw-720%2Cdpr-2%2Cf-png%2Fwp-content%2Fuploads%2Fsave-data-demo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fdemo%2Fimagekitwebsite%2Ftr%3Aw-720%2Cdpr-2%2Cf-png%2Fwp-content%2Fuploads%2Fsave-data-demo.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ImageKit &lt;a href="https://docs.imagekit.io/features/image-optimization/data-saver-mode" rel="noopener noreferrer"&gt;supports Save-Data mode&lt;/a&gt; and when enabled, it will deliver a low-quality image to reduce data transfer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  ECT, RTT, and Downlink
&lt;/h3&gt;

&lt;p&gt;Besides &lt;code&gt;Save-Data&lt;/code&gt;  hint, we also have &lt;code&gt;ECT&lt;/code&gt;, &lt;code&gt;RTT&lt;/code&gt; and &lt;code&gt;Downlink&lt;/code&gt; client hints - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ECT&lt;/code&gt; - &lt;em&gt;Effective Connection Type&lt;/em&gt; e.g. **&lt;code&gt;4g&lt;/code&gt;, &lt;code&gt;3g&lt;/code&gt;, &lt;code&gt;2g&lt;/code&gt;, and &lt;code&gt;slow-2g&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RTT&lt;/code&gt; - &lt;em&gt;Round Trip Time&lt;/em&gt;, in milliseconds, on the application layer.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Downlink&lt;/code&gt; - Approximate downstream speed of the user’s connection in megabits per second (Mbps).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/client-hints" rel="noopener noreferrer"&gt;Jeremy Wagner&lt;/a&gt; wrote in Google Web Fundamentals -  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Adaptive performance is the idea that we can adjust how we deliver resources based on the information client hints makes available to us; specifically, information surrounding the current state of the user’s network connection.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Time is the key&lt;/strong&gt; — Taking forever to load a high-quality image on a slow network is more frustrating for your users than showing a low-quality variant that loads quickly. You can use these network client hints to &lt;a href="https://github.com/malchata/client-hints-example/blob/master/includes/functions.php#L8" rel="noopener noreferrer"&gt;calculate a score of client&lt;/a&gt;’&lt;a href="https://github.com/malchata/client-hints-example/blob/master/includes/functions.php#L8" rel="noopener noreferrer"&gt;s network connection quality&lt;/a&gt; and accordingly change your logic on server to help users on the slow network have decent experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitation of client hints
&lt;/h2&gt;

&lt;p&gt;Client hints look pretty amazing. They automate responsive images without major markup changes. But there are some limitations with client hints -&lt;/p&gt;

&lt;h3&gt;
  
  
  Client hints don’t work in all browsers
&lt;/h3&gt;

&lt;p&gt;At the moment, they are only supported in Chrome and Chromium-based browsers, Edge, and Opera.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_7E0F730B8904F9164DE50ED2794395678260F68A4F209B065252D2D8D36F2F6A_1604033274584_Screenshot%2B2020-10-30%2Bat%2B10.16.44%2BAM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_7E0F730B8904F9164DE50ED2794395678260F68A4F209B065252D2D8D36F2F6A_1604033274584_Screenshot%2B2020-10-30%2Bat%2B10.16.44%2BAM.png" alt="Can I Use - https://caniuse.com/client-hints-dpr-width-viewport"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-origin client hints removed in Chrome 67 in the desktop version
&lt;/h3&gt;

&lt;p&gt;After client hints landing in Chrome 35, there were concerns around tracking users across multiple websites because of the device-related information passed through client hints.&lt;/p&gt;

&lt;p&gt;Essentially, sending highly granular data, such as image and viewport width, may help identify users across multiple requests. More importantly, there was no mechanism to control which origin should receive this. The moment you opt-in for client hints, all image resource type request will start sharing device-specific data with origins.&lt;/p&gt;

&lt;p&gt;If your website is hosted on &lt;code&gt;www.example.com&lt;/code&gt; and images are on &lt;code&gt;www.example.com/image.jpg&lt;/code&gt; it is fine. But if images on &lt;code&gt;www.images.third-party-service.com/image.jpg&lt;/code&gt; have the same data, it may reveal the same information about the user to other origins that may not have had access to it before.&lt;/p&gt;

&lt;p&gt;As a result, the Chrome team removed cross-origin client hints in the desktop version of Chrome 67, but they &lt;a href="https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/8RBFue7RMXQ/7TF4VPVzBAAJ" rel="noopener noreferrer"&gt;still work in mobile&lt;/a&gt;. These restrictions will be removed soon when work on &lt;a href="https://wicg.github.io/feature-policy/" rel="noopener noreferrer"&gt;Feature Policy&lt;/a&gt; is complete.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your server should support client hints
&lt;/h3&gt;

&lt;p&gt;For client hints to work, your server should understand them and respond with an appropriate image.&lt;/p&gt;

&lt;p&gt;For example, the servers should be able to - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deliver the right size image based on the value of the &lt;code&gt;Width&lt;/code&gt; client hint.&lt;/li&gt;
&lt;li&gt;Serve images in WebP or AVIF format based on the value of the &lt;code&gt;Accept&lt;/code&gt; client hint.&lt;/li&gt;
&lt;li&gt;Select the right image variant based on the value of the &lt;code&gt;DPR&lt;/code&gt; client hint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fortunately, you can automate all this using an image CDN like &lt;a href="https://imagekit.io/" rel="noopener noreferrer"&gt;ImageKit.io&lt;/a&gt;, which supports client hints out of the box.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caching on CDN can be tricky
&lt;/h3&gt;

&lt;p&gt;You would want to &lt;a href="https://imagekit.io/blog/ultimate-guide-to-http-caching-for-static-assets/" rel="noopener noreferrer"&gt;cache your static resources&lt;/a&gt; like images to accelerate the download and decrease the load on your origin server. But with client hints in the mix, it can be tricky.&lt;/p&gt;

&lt;p&gt;Usually, a CDN looks for the objects in the cache based on the resource URL. However, when the server changes the response based on other request HTTP headers i.e. client hints, the CDN has to be aware of how to respond to future requests. Essentially if we are changing the response based on the &lt;code&gt;Accept&lt;/code&gt; request header value, we will have to configure the CDN to store seperate response in cache based on the value of the &lt;code&gt;Accept&lt;/code&gt; request header.&lt;/p&gt;

&lt;p&gt;You can use the &lt;code&gt;Vary&lt;/code&gt; response header to indicate CDN and intermediate proxies to maintain different cache objects based on header names in &lt;code&gt;Vary&lt;/code&gt;. For example -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Vary: Accept, DPR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that CDN and intermediate proxies should take the value of the &lt;code&gt;Accept&lt;/code&gt; and &lt;code&gt;DPR&lt;/code&gt; request header in account in addition to resource URL while storing and looking up objects in the cache. The cache lookup key should be &lt;code&gt;Accept + DPR + resource URL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is important to note that you should not set &lt;code&gt;Vary: User-agent&lt;/code&gt; because there could be a huge number of unique values for the &lt;code&gt;User-Agent&lt;/code&gt; request header, resulting in a lower cache hit ratio on the CDN.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An image CDN like &lt;a href="https://imagekit.io/" rel="noopener noreferrer"&gt;ImageKit.io&lt;/a&gt; already takes care of CDN caching while ensuring the cache hit ratio is high.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Chapter 8 - Responsive images in CSS
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;background-image&lt;/code&gt; is a very powerful CSS property that allows you to insert images on elements other than &lt;code&gt;img&lt;/code&gt;. What you have learned so far about responsive images deals with only HTML markup. Let’s see how to implement responsive images in CSS.&lt;/p&gt;

&lt;p&gt;We have the following use-cases to cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Art direction i.e. loading entirely different images based on screen width. In HTML, we used the &lt;code&gt;picture&lt;/code&gt; element. In CSS, we can use old fashioned media queries.&lt;/li&gt;
&lt;li&gt;Providing high-resolution image variants to let the browser make a choice. In HTML &lt;code&gt;srcset&lt;/code&gt; attribute provides the browser with &lt;code&gt;1x&lt;/code&gt;, &lt;code&gt;2x&lt;/code&gt;, and &lt;code&gt;3x&lt;/code&gt; variants of the same image. In CSS, we have the option to use &lt;code&gt;image-set&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;In CSS media query alone is enough to implement responsive images. However, &lt;code&gt;image-set&lt;/code&gt; is similar to &lt;code&gt;srcset&lt;/code&gt; because it provides the options and lets the browser choose the image. But it is not equivalent to srcset.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Art direction in CSS — loading an entirely different image based on screen size
&lt;/h2&gt;

&lt;p&gt;In HTML, we have a &lt;code&gt;picture&lt;/code&gt; element to load an image conditionally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/large.jpg"&lt;/span&gt;
          &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 800px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/small.jpg"&lt;/span&gt;
          &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 400px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/large.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In CSS, we have media queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.element&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url(small.jpg)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-repeat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;no-repeat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;contain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;background-position-x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;800px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.element&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url(large.jpg)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, on small screen &lt;code&gt;background-image: url(small.jpg)&lt;/code&gt;  is applied and when viewport width is greater than or equal to 800px, &lt;code&gt;background-image: url(large.jpg)&lt;/code&gt; is applied.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loading high-resolution images based on device pixel ratio
&lt;/h2&gt;

&lt;p&gt;In HTML we have &lt;code&gt;srcset&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg"&lt;/span&gt; 
     &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg 1x,
             image_2x.jpg 2x"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In CSS, we can use &lt;code&gt;image-set&lt;/code&gt; and media queries.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Using &lt;code&gt;image-set&lt;/code&gt; to provide high resolution images variants&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.demo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url(image.jpg)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="err"&gt;//&lt;/span&gt; &lt;span class="err"&gt;fallback&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;-webkit-image-set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="sx"&gt;url(image.jpg)&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="sx"&gt;url(image_2x.jpg)&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;  
  &lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;image-set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="sx"&gt;url(image.jpg)&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="sx"&gt;url(image_2x.jpg)&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;image-set&lt;/code&gt; is not supported, the fallback &lt;code&gt;background-image: url(image.jpg)&lt;/code&gt; will be applied.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Using media queries&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.demo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url(image.jpg)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="err"&gt;//&lt;/span&gt; &lt;span class="err"&gt;Standard&lt;/span&gt; &lt;span class="err"&gt;syntax&lt;/span&gt; &lt;span class="err"&gt;supported&lt;/span&gt; &lt;span class="err"&gt;in&lt;/span&gt; &lt;span class="err"&gt;Chrome,&lt;/span&gt; &lt;span class="err"&gt;Firefox,&lt;/span&gt; &lt;span class="err"&gt;and&lt;/span&gt; &lt;span class="err"&gt;Opera&lt;/span&gt;
  &lt;span class="err"&gt;@media&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="py"&gt;min-resolution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2dppx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;-webkit-min-device-pixel-ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;/* For Safari &amp;amp; Android Browser */&lt;/span&gt; 
  &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;demo&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url(image_2x.jpg)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Chapter 9 - Lazy load responsive images
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What is Lazy loading images?
&lt;/h2&gt;

&lt;p&gt;As Rahul Nanwani wrote in &lt;a href="https://imagekit.io/blog/lazy-loading-images-complete-guide/" rel="noopener noreferrer"&gt;lazy loading images guide&lt;/a&gt; -&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lazy Loading Images is a set of techniques in web and application development that defer the loading of images on a page to a later point in time - when those images are actually needed, instead of loading them upfront. These techniques help in improving performance, better utilization of the device’s resources, and reducing associated costs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Usually, to implement lazy loading in HTML, instead of &lt;code&gt;src&lt;/code&gt; or &lt;code&gt;srcset&lt;/code&gt; attributes, we use &lt;code&gt;data-src&lt;/code&gt; or &lt;code&gt;data-srcset&lt;/code&gt; so that browser does not load images during speculative parsing. Later on, when Javascript is executed, and the user has scrolled near the image element, we load the actual image and update the &lt;code&gt;src&lt;/code&gt; or &lt;code&gt;srcset&lt;/code&gt; attribute’s value.&lt;/p&gt;

&lt;p&gt;Two very popular lazy loading libraries &lt;a href="https://github.com/aFarkas/lazysizes" rel="noopener noreferrer"&gt;lazysizes&lt;/a&gt; and &lt;a href="https://github.com/verlok/vanilla-lazyload" rel="noopener noreferrer"&gt;vanilla-lazyload&lt;/a&gt; support responsive images out of the box. In this guide, we will share a few examples of lazysizes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lazy loading responsive images in srcset and sizes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
    &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 1000px) 930px, 90vw"&lt;/span&gt;
    &lt;span class="na"&gt;data-srcset=&lt;/span&gt;&lt;span class="s"&gt;"small.jpg 500w,
                 medium.jpg 640w,
                 big.jpg 1024w"&lt;/span&gt;
    &lt;span class="na"&gt;data-src=&lt;/span&gt;&lt;span class="s"&gt;"medium.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"lazyload"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using low quality placeholder in lazy loading
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"low-quaity-placeholder.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 1000px) 930px, 90vw"&lt;/span&gt;
    &lt;span class="na"&gt;data-srcset=&lt;/span&gt;&lt;span class="s"&gt;"small.jpg 500w,
                 medium.jpg 640w,
                 big.jpg 1024w"&lt;/span&gt;
    &lt;span class="na"&gt;data-src=&lt;/span&gt;&lt;span class="s"&gt;"medium.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"lazyload"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lazy loading images in picture element
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
          &lt;span class="na"&gt;data-srcset=&lt;/span&gt;&lt;span class="s"&gt;"500.jpg"&lt;/span&gt;
          &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 500px)"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
          &lt;span class="na"&gt;data-srcset=&lt;/span&gt;&lt;span class="s"&gt;"1024.jpg"&lt;/span&gt;
          &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 1024px)"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
          &lt;span class="na"&gt;data-srcset=&lt;/span&gt;&lt;span class="s"&gt;"1200.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"fallback-image.jpg"&lt;/span&gt;
          &lt;span class="na"&gt;data-src=&lt;/span&gt;&lt;span class="s"&gt;"1024.jpg"&lt;/span&gt;
          &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"lazyload"&lt;/span&gt;
          &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"image with artdirection"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Chapter 10 - How to verify responsive image implementation?
&lt;/h2&gt;

&lt;p&gt;After you implement responsive images, it's essential to verify that the right image is being loaded on different devices. Let’s discuss how various tools and browser's developer console can help us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using ImageKit website analyzer
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://imagekit.io/website-analyzer/" rel="noopener noreferrer"&gt;ImageKit website analyzer&lt;/a&gt; is a tailor-made tool to find our image related issues on the webpage. It loads the webpage in a headless browser. All the image requests are monitored and compared against the optimized version fetched from ImageKit. &lt;/p&gt;

&lt;p&gt;You will get a report like below. Look under &lt;strong&gt;Properly resize images&lt;/strong&gt; to see if images are in the right sizes. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fimagekit-website-analyzer-audit_pKqN97Pl8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fimagekit-website-analyzer-audit_pKqN97Pl8.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This tool also provides an image by image explanation for all images on the webpage like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_7E0F730B8904F9164DE50ED2794395678260F68A4F209B065252D2D8D36F2F6A_1605154179992_Screenshot%2B2020-11-12%2Bat%2B9.39.30%2BAM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_7E0F730B8904F9164DE50ED2794395678260F68A4F209B065252D2D8D36F2F6A_1605154179992_Screenshot%2B2020-11-12%2Bat%2B9.39.30%2BAM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This tool provides image analysis reports for desktop and mobile. However, at the moment, it does not take into account the device pixel ratio, so you will have to consider that, especially while looking at the mobile report.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Using Lighthouse
&lt;/h2&gt;

&lt;p&gt;You can use &lt;a href="https://developers.google.com/web/tools/lighthouse" rel="noopener noreferrer"&gt;Lighthouse&lt;/a&gt; to verify responsive images are implemented correctly. Run the Lighthouse Performance Audit for Mobile &amp;amp; Desktop and look for the &lt;strong&gt;Properly size images&lt;/strong&gt; audit results.&lt;/p&gt;

&lt;p&gt;This will show all the images that aren't appropriately sized based on the page layout.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_7E0F730B8904F9164DE50ED2794395678260F68A4F209B065252D2D8D36F2F6A_1605146844250_uses-responsive-images.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_7E0F730B8904F9164DE50ED2794395678260F68A4F209B065252D2D8D36F2F6A_1605146844250_uses-responsive-images.png" alt="Source - https://web.dev/uses-responsive-images/"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Manually verifying responsive images
&lt;/h2&gt;

&lt;p&gt;You can use the Chrome device emulator to load a webpage on different devices and see the image requests in the network tab. Few points to note before starting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browser cache should be disabled - so that with subsequent reloads, we can see which image resources are being requested.&lt;/li&gt;
&lt;li&gt;Ensure device pixel ratio is added, as shown in the screenshot below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fchrome-emulate-enable-dpr_QdiHs9Mv5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fchrome-emulate-enable-dpr_QdiHs9Mv5.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now open the webpage and hover over the image element to see its required CSS pixel width. Multiple it with DPR value to get the required width of the image resource. &lt;/p&gt;

&lt;p&gt;For example here, &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fverifying-responsive-images-srcset-sizes_ygIzVisE6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fikmedia%2Fverifying-responsive-images-srcset-sizes_ygIzVisE6.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DPR value - 2.6&lt;/li&gt;
&lt;li&gt;CSS pixel width - 206&lt;/li&gt;
&lt;li&gt;Required image size - 206 × 2.6 = 535.6&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Available options based on &lt;code&gt;srcset&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;srcset="https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-225 225w,
        https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-300 300w,
        https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-350 350w,
        https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-640 640w"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the nearest candidate is a 640px wide image, and the browser downloads this image.  You can use the same technique to see if the right size images are loaded or not.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Why can't we do this using CSS or JavaScript?
&lt;/h2&gt;

&lt;p&gt;It's logical to think that we have all the information about browser, device, and layout and can use Javascript to load the right size image. However, this will delay the loading of image resources and defeat the whole purpose of rendering images quickly. Modern browsers don’t wait for Javascript and CSS to be parsed and executed before it triggers the image request. The browser scans the whole HTML and looks for image resources without waiting for Javascript to execute. That is why we need to use the &lt;code&gt;srcset&lt;/code&gt;, &lt;code&gt;sizes&lt;/code&gt;, and &lt;code&gt;picture&lt;/code&gt; element to implement responsive images. Learn how the browser loads a webpage to understand this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can I use both density and width descriptor in srcset?
&lt;/h2&gt;

&lt;p&gt;No. As per the &lt;a href="https://html.spec.whatwg.org/multipage/images.html#image-candidate-string" rel="noopener noreferrer"&gt;specifications&lt;/a&gt; about how &lt;code&gt;srcset&lt;/code&gt;  is parsed - If an image candidate string for an element has the width descriptor specified, all other image candidate strings for that element must also have the width descriptor specified. Also, if an element has a size attribute present, all image candidate strings for that element must have the width descriptor specified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we need sizes attribute with srcset?
&lt;/h2&gt;

&lt;p&gt;So that browser can trigger image load as part of preloading instead of waiting for CSS to download &amp;amp; parse. Learn how the browser loads a webpage to understand this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we use width and not a height in srcset?
&lt;/h2&gt;

&lt;p&gt;We have been specifying only image widths in &lt;code&gt;srcset&lt;/code&gt; and not height because the vast majority of responsive design is width constrained and not height, so to keep things simple, the specification only deals in widths.&lt;/p&gt;

&lt;h2&gt;
  
  
  What sizes values should I declare?
&lt;/h2&gt;

&lt;p&gt;The value of the &lt;code&gt;sizes&lt;/code&gt; attribute should specify the size of the rendered image in CSS pixel. It could be an absolute value e.g. &lt;code&gt;250px&lt;/code&gt; or relative to viewport size e.g. &lt;code&gt;33vw&lt;/code&gt; means 33% of viewport width. You can use comma-separated media conditions in the &lt;code&gt;sizes&lt;/code&gt; attribute to tell how rendered image width changes based on viewport size. For example -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;sizes="(max-width: 300px) 100vw, (max-width: 600px) 50vw, (max-width: 900px) 33vw, 900px"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What image sizes should I provide in srcset?
&lt;/h2&gt;

&lt;p&gt;First, think about your layout i.e., CSS. Then accordingly, write  &lt;code&gt;sizes&lt;/code&gt;. And finally, choose breakpoints for  &lt;code&gt;srcset&lt;/code&gt; considering different DPR values and effective image sizes you need 🙌.&lt;/p&gt;

&lt;h2&gt;
  
  
  How should I generate different size image assets?
&lt;/h2&gt;

&lt;p&gt;You will need to provide different size image variants to implement responsive images. On a typical e-commerce or news website, this could be a huge problem as we are dealing with thousands of photos. The solution is to use an &lt;a href="https://imagekit.io/blog/what-is-image-cdn-guide/" rel="noopener noreferrer"&gt;image CDN&lt;/a&gt;. ImageKit.io is an image CDN that provides real-time image resizing, automatic image format conversion, and optimization. It offers a &lt;a href="https://imagekit.io/registration" rel="noopener noreferrer"&gt;forever free plan&lt;/a&gt; with generous bandwidth limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you make an image responsive in HTML?
&lt;/h2&gt;

&lt;p&gt;If you are wondering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to load different images based on screen size?&lt;/li&gt;
&lt;li&gt;How to change image size for mobile devices?&lt;/li&gt;
&lt;li&gt;How to display different images on mobile and desktop devices?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, know that all of these use-cases are related and can be solved using the latest responsive image techniques that we have discussed in this guide.&lt;/p&gt;

&lt;p&gt;Often you will only need &lt;code&gt;srcset&lt;/code&gt; attribute. In few cases you might want to use &lt;code&gt;picture&lt;/code&gt; tag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Srcset not working
&lt;/h2&gt;

&lt;p&gt;You could face one problem while using &lt;code&gt;srcset&lt;/code&gt; in responsive images is that the browser is always using the largest image available. There could be two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you resized the window to test responsive image implementation and the browser has once loaded a high resolution bigger image, then it won’t load a smaller image again because it can use the largest one from the cache. It saves time &amp;amp; bandwidth. That is the whole point. It is specific to Chrome. &lt;/li&gt;
&lt;li&gt;You need to consider the DPR value into account. On the retina display, the browser will go for a wider image based on options available in &lt;code&gt;srcset&lt;/code&gt;. If 300px wide image is required and DPR is 2, the browser needs at-least 600px wide image. It might be confusing as you were expecting it to pick a 300px wide option from &lt;code&gt;srcset&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Client hints not working
&lt;/h2&gt;

&lt;p&gt;After client hints landing in Chrome 35, there were concerns around tracking users across multiple websites because of the device-related information passed through client hints. As a result, the Chrome team removed cross-origin client hints in the desktop version of Chrome 67, but they &lt;a href="https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/8RBFue7RMXQ/7TF4VPVzBAAJ" rel="noopener noreferrer"&gt;still work in mobile&lt;/a&gt;. These restrictions will be removed soon when work on &lt;a href="https://wicg.github.io/feature-policy/" rel="noopener noreferrer"&gt;Feature Policy&lt;/a&gt; is complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to make a background image responsive?
&lt;/h2&gt;

&lt;p&gt;Setting width and height is not enough when it comes to using background images. You can leverage the latest techniques to implement responsive images in CSS e.g. &lt;code&gt;image-set&lt;/code&gt; and well-known media queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsive images srcset vs picture?
&lt;/h2&gt;

&lt;p&gt;More often than not, you will only need srcset with sizes while implementing responsive images. That is because the primary use-case of responsive images is to load the right size image on different devices e.g. mobile or desktop. However, a picture tag is there if you need to implement art direction i.e. to load an entirely different image based on available screen width or device orientation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Picture tag not working
&lt;/h2&gt;

&lt;p&gt;If the picture element is not working, ensure that you have the &lt;code&gt;img&lt;/code&gt; element inside the picture element. This acts as a fallback when the browser doesn’t support the picture element. You can also use a &lt;a href="https://github.com/scottjehl/picturefill" rel="noopener noreferrer"&gt;polyfill for picture&lt;/a&gt; element.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to make images responsive in WordPress?
&lt;/h2&gt;

&lt;p&gt;Responsive images landed in WordPress 4.4, making it easier for theme developers to implement responsive images in their themes. As soon as an image is uploaded in the media library, WordPress creates multiple different size variants and store them. When you embed the image in a post, the &lt;code&gt;img&lt;/code&gt; element has &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Default sizes attribute&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By default, the value of the &lt;code&gt;size&lt;/code&gt; attribute is equivalent to -&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(max-width: {{image-width}}px) 100vw, {{image-width}}px&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;However, as a theme developer, you have the best knowledge of ideal image size, and you should override this default, as discussed below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuring responsive images for your theme&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Theme developers should use &lt;code&gt;wp_calculate_image_sizes&lt;/code&gt; helper function to create the &lt;code&gt;sizes&lt;/code&gt; attribute for an image. &lt;/p&gt;

&lt;p&gt;For example, the below hook will apply to all content and featured/thumbnail images. Thanks to &lt;a href="https://www.smashingmagazine.com/2015/12/responsive-images-in-wordpress-core/" rel="noopener noreferrer"&gt;Tim Evko&lt;/a&gt; for the code snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;adjust_image_sizes_attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$sizes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$size&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$sizes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$sizes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;add_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'wp_calculate_image_sizes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'adjust_image_sizes_attr'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also hook into &lt;code&gt;wp_calculate_image_srcset&lt;/code&gt; to calculate the image sources to include in a &lt;code&gt;srcset&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Responsive images in WordPress before 4.4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before version 4.4, you have to use the &lt;a href="https://wordpress.org/plugins/ricg-responsive-images/" rel="noopener noreferrer"&gt;RICG Responsive Images&lt;/a&gt; plugin. This plugin works by including all available image sizes for each image upload. Whenever WordPress outputs the image through the media uploader, or whenever a featured image is generated, those sizes will be included in the image tag via the &lt;code&gt;srcset&lt;/code&gt; attribute. This plugin doesn’t add a &lt;code&gt;sizes&lt;/code&gt; attribute, though.&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions
&lt;/h2&gt;

&lt;p&gt;We hope this guide helped you understand the responsive images in HTML and CSS. If you have a question, feel free to comment or email on &lt;a href="mailto:support@imagekit.io"&gt;support@imagekit.io&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>html</category>
    </item>
  </channel>
</rss>
