<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/css" href="https://www.aaron-gustafson.com/c/feed.min.css" ?><feed xmlns="http://www.w3.org/2005/Atom"
      xmlns:amg="https://www.aaron-gustafson.com.com/amg-dtd/"><title>Aaron Gustafson: Content tagged images</title><subtitle>The latest 20 posts and links tagged images.</subtitle><id>https://www.aaron-gustafson.com</id><link href="https://www.aaron-gustafson.com/feeds/images.xml" rel="self"/><link href="https://www.aaron-gustafson.com"/><author><name>Aaron Gustafson</name><uri>https://www.aaron-gustafson.com</uri></author><updated>2025-12-10T17:15:54Z</updated><entry><id>https://www.aaron-gustafson.com/notebook/lazy-loading-images-based-on-screen-size/</id><title type="html"><![CDATA[✍🏻 Lazy Loading Images Based on Screen Size]]></title><link href="https://www.aaron-gustafson.com/notebook/lazy-loading-images-based-on-screen-size/" rel="alternate" type="text/html" /><published>2025-12-10T17:15:54Z</published><content type="html" xml:base="https://www.aaron-gustafson.com"><![CDATA[<p>Native lazy loading and <code>srcset</code> are great, but they have a limitation: they always load <em>some</em> variant of the image. The <code>lazy-img</code> web component takes a different approach—it can completely skip loading images when they don’t meet your criteria, whether that’s screen size, container size, or visibility in the viewport.</p><p>This is particularly valuable for mobile users on slow connections or limited data plans. If an image is only meaningful on larger screens, why waste their bandwidth loading it at all?</p><h2 id="the-performance-benefit" tabindex="-1"><a class="header-anchor" href="#the-performance-benefit" aria-hidden="true">#</a> The performance benefit</h2><p>Unlike <code>picture</code> or <code>srcset</code>, which always load some image variant, <code>lazy-img</code> can <strong>completely skip loading images</strong> on screens or containers below your specified threshold. Set <code>min-inline-size=&quot;768px&quot;</code> and mobile users will never download that image at all—saving data and speeding up page loads.</p><p>Once an image is loaded, however, it remains loaded even if the viewport or container is resized below the threshold. This is intentional—the component prevents unnecessary downloads but doesn’t unload images already in memory. You can control visibility with CSS if needed using the <code>loaded</code> and <code>qualifies</code> attributes (which we’ll get to shortly).</p><h2 id="basic-usage" tabindex="-1"><a class="header-anchor" href="#basic-usage" aria-hidden="true">#</a> Basic usage</h2><p>The <code>lazy-img</code> works pretty much identically to a regular <code>img</code> element, with all the attributes you know and love:</p><pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>lazy-img</span><span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>image.jpg<span class="token punctuation">”</span></span><span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>A beautiful image<span class="token punctuation">”</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>lazy-img</span><span class="token punctuation">&gt;</span></span></code></pre><p>But that’s not very interesting. The real power comes from conditional loading.</p><h2 id="container-queries-(default)" tabindex="-1"><a class="header-anchor" href="#container-queries-(default)" aria-hidden="true">#</a> Container queries (default)</h2><p>Load an image only when its container reaches a minimum width:</p><pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>lazy-img</span><span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>large-image.jpg<span class="token punctuation">”</span></span><span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>Large image<span class="token punctuation">”</span></span><span class="token attr-name">min-inline-size</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>500px<span class="token punctuation">”</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>lazy-img</span><span class="token punctuation">&gt;</span></span></code></pre><p>The image loads when the <code>lazy-img</code> element’s container reaches 500px wide. This is the default query mode—it uses <code>ResizeObserver</code> to watch the container size.</p><h2 id="media-queries" tabindex="-1"><a class="header-anchor" href="#media-queries" aria-hidden="true">#</a> Media queries</h2><p>You can lazy load images based on viewport width instead by switching to media query mode:</p><pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>lazy-img</span><span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>desktop-image.jpg<span class="token punctuation">”</span></span><span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>Desktop image<span class="token punctuation">”</span></span><span class="token attr-name">min-inline-size</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>768px<span class="token punctuation">”</span></span><span class="token attr-name">query</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>media<span class="token punctuation">”</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>lazy-img</span><span class="token punctuation">&gt;</span></span></code></pre><p>With this configuration, the image loads when the browser window is at least 768px wide.</p><h2 id="view-mode-(scroll-based-loading)" tabindex="-1"><a class="header-anchor" href="#view-mode-(scroll-based-loading)" aria-hidden="true">#</a> View mode (scroll-based loading)</h2><p>Load images when they scroll into view using <code>IntersectionObserver</code> by switching to the “view” query type:</p><pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>lazy-img</span><span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>image.jpg<span class="token punctuation">”</span></span><span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>Loads when scrolled into view<span class="token punctuation">”</span></span><span class="token attr-name">query</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>view<span class="token punctuation">”</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>lazy-img</span><span class="token punctuation">&gt;</span></span></code></pre><p>The default behavior (<code>view-range-start=&quot;entry 0%&quot;</code>) loads as soon as any part of the image enters the viewport.</p><p>Control when images load with the <code>view-range-start</code> attribute:</p><p><strong>Load when 50% visible:</strong></p><pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>lazy-img</span><span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>image.jpg<span class="token punctuation">”</span></span><span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>Loads when half visible<span class="token punctuation">”</span></span><span class="token attr-name">query</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>view<span class="token punctuation">”</span></span><span class="token attr-name">view-range-start</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>entry 50%<span class="token punctuation">”</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>lazy-img</span><span class="token punctuation">&gt;</span></span></code></pre><p><strong>Preload before entering viewport:</strong></p><pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>lazy-img</span><span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>image.jpg<span class="token punctuation">”</span></span><span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>Preloads 200px before visible<span class="token punctuation">”</span></span><span class="token attr-name">query</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>view<span class="token punctuation">”</span></span><span class="token attr-name">view-range-start</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>entry -200px<span class="token punctuation">”</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>lazy-img</span><span class="token punctuation">&gt;</span></span></code></pre><p>This creates a smooth user experience—images are already loaded by the time users scroll to them.</p><h2 id="responsive-images" tabindex="-1"><a class="header-anchor" href="#responsive-images" aria-hidden="true">#</a> Responsive images</h2><p>As with regular images, you can use <code>srcset</code> and <code>sizes</code> for responsive images:</p><pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>lazy-img</span><span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>image-800.jpg<span class="token punctuation">”</span></span><span class="token attr-name">srcset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>image-400.jpg 400w,image-800.jpg 800w,image-1200.jpg 1200w<span class="token punctuation">”</span></span><span class="token attr-name">sizes</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>(max-width: 600px) 400px,(max-width: 1000px) 800px,1200px<span class="token punctuation">”</span></span><span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>Responsive image<span class="token punctuation">”</span></span><span class="token attr-name">min-inline-size</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>400px<span class="token punctuation">”</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>lazy-img</span><span class="token punctuation">&gt;</span></span></code></pre><p>The component waits until the conditions are met before loading a real image and the browser takes over from there.</p><h2 id="named-breakpoints" tabindex="-1"><a class="header-anchor" href="#named-breakpoints" aria-hidden="true">#</a> Named breakpoints</h2><p>You can also define named breakpoints using CSS custom properties:</p><pre class="language-css" tabindex="0"><code class="language-css"><span class="token selector">:root</span><span class="token punctuation">{</span><span class="token property">–lazy-img-mq</span><span class="token punctuation">:</span> small<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token atrule"><span class="token rule">@media</span><span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> 768px<span class="token punctuation">)</span></span><span class="token punctuation">{</span><span class="token selector">:root</span><span class="token punctuation">{</span><span class="token property">–lazy-img-mq</span><span class="token punctuation">:</span> medium<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token atrule"><span class="token rule">@media</span><span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> 1024px<span class="token punctuation">)</span></span><span class="token punctuation">{</span><span class="token selector">:root</span><span class="token punctuation">{</span><span class="token property">–lazy-img-mq</span><span class="token punctuation">:</span> large<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span></code></pre><p>Then reference them in your markup:</p><pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>lazy-img</span><span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>image.jpg<span class="token punctuation">”</span></span><span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>Image with named breakpoints<span class="token punctuation">”</span></span><span class="token attr-name">named-breakpoints</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>medium, large<span class="token punctuation">”</span></span><span class="token attr-name">query</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>media<span class="token punctuation">”</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>lazy-img</span><span class="token punctuation">&gt;</span></span></code></pre><p>The image loads when <code>–lazy-img-mq</code> matches “medium” or “large”.</p><h2 id="preventing-layout-shift" tabindex="-1"><a class="header-anchor" href="#preventing-layout-shift" aria-hidden="true">#</a> Preventing layout shift</h2><p>As with regular images, don’t forget to use <code>width</code> and <code>height</code> attributes to prevent Cumulative Layout Shift (CLS):</p><pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>lazy-img</span><span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>image.jpg<span class="token punctuation">”</span></span><span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>A beautiful image<span class="token punctuation">”</span></span><span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>800<span class="token punctuation">”</span></span><span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>600<span class="token punctuation">”</span></span><span class="token attr-name">min-inline-size</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">“</span>768px<span class="token punctuation">”</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>lazy-img</span><span class="token punctuation">&gt;</span></span></code></pre><p>The browser reserves the correct space while the image loads, preventing content from jumping around.</p><h2 id="state-attributes-for-styling" tabindex="-1"><a class="header-anchor" href="#state-attributes-for-styling" aria-hidden="true">#</a> State attributes for styling</h2><p>The component provides <code>loaded</code> and <code>qualifies</code> attributes you can use in CSS:</p><pre class="language-css" tabindex="0"><code class="language-css"><span class="token comment">/* Hide images that loaded but no longer meet conditions <em>/</span><span class="token selector">lazy-img[loaded]:not([qualifies])</span><span class="token punctuation">{</span><span class="token property">display</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token comment">/</em> Show a placeholder for images that qualify but haven’t loaded */</span><span class="token selector">lazy-img[qualifies]:not([loaded])::before</span><span class="token punctuation">{</span><span class="token property">content</span><span class="token punctuation">:</span><span class="token string">“Loading…”</span><span class="token punctuation">;</span><span class="token property">display</span><span class="token punctuation">:</span> block<span class="token punctuation">;</span><span class="token property">padding</span><span class="token punctuation">:</span> 2em<span class="token punctuation">;</span><span class="token property">background</span><span class="token punctuation">:</span> #f0f0f0<span class="token punctuation">;</span><span class="token property">text-align</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span><span class="token punctuation">}</span></code></pre><h2 id="events" tabindex="-1"><a class="header-anchor" href="#events" aria-hidden="true">#</a> Events</h2><p>If you crave control, you can add your own functionality by listening for when images load:</p><pre class="language-javascript" tabindex="0"><code class="language-javascript"><span class="token keyword">const</span> lazyImg <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">“lazy-img”</span><span class="token punctuation">)</span><span class="token punctuation">;</span>lazyImg<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">“lazy-img:loaded”</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span><span class="token operator">=&gt;</span><span class="token punctuation">{</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">“Image loaded:”</span><span class="token punctuation">,</span> event<span class="token punctuation">.</span>detail<span class="token punctuation">.</span>src<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><h2 id="performance" tabindex="-1"><a class="header-anchor" href="#performance" aria-hidden="true">#</a> Performance</h2><p>The component is highly optimized:</p><ul><li><strong>Throttled resize</strong>: Resize events are throttled to prevent excessive checks</li><li><strong>Shared <code>ResizeObserver</code></strong>: Multiple images observing the same container share a single ResizeObserver</li><li><strong>Shared window resize listener</strong>: Media query mode shares a single window resize listener</li><li><strong>Shared <code>IntersectionObserver</code></strong>: View mode with the same <code>view-range-start</code> shares an <code>IntersectionObserver</code></li><li><strong>Clean disconnection</strong>: Properly cleans up observers when elements are removed</li></ul><p>Even with hundreds of <code>lazy-img</code> elements on a page, performance remains excellent.</p><h2 id="progressive-enhancement" tabindex="-1"><a class="header-anchor" href="#progressive-enhancement" aria-hidden="true">#</a> Progressive enhancement</h2><p>If JavaScript fails to load, images simply don’t appear (unless using immediate loading mode). This might sound problematic, but for non-critical images—decorative graphics, supplementary screenshots, marketing imagery—it’s often exactly what you want. Your content remains accessible; you just lose the enhancements.</p><p>For critical images that are part of your content, use standard <code>img</code> tags. Use <code>lazy-img</code> for conditional enhancements.</p><h2 id="demo" tabindex="-1"><a class="header-anchor" href="#demo" aria-hidden="true">#</a> Demo</h2><p>Explore <a href="https://aarongustafson.github.io/lazy-img/demo/">the demo</a> to see container queries, media queries, scroll-based loading, and more in action:</p><figure id="fig-2025-12-06-04" class="media-container"><fullscreen-control class="talk__slides__embed video-embed__video"><iframe src="https://aarongustafson.github.io/lazy-img/demo/" class="talk__slides__embed video-embed__video" frameborder="0"></iframe></fullscreen-control></figure><h2 id="grab-it" tabindex="-1"><a class="header-anchor" href="#grab-it" aria-hidden="true">#</a> Grab it</h2><p>Check out the project on <a href="https://github.com/aarongustafson/lazy-img">GitHub</a>. Install via npm:</p><pre class="language-bash" tabindex="0"><code class="language-bash"><span class="token function">npm</span><span class="token function">install</span> @aarongustafson/lazy-img</code></pre><p>Import and use:</p><pre class="language-javascript" tabindex="0"><code class="language-javascript"><span class="token keyword">import</span><span class="token string">“@aarongustafson/lazy-img”</span><span class="token punctuation">;</span></code></pre><p>Based on my original <a href="https://github.com/easy-designs/easy-lazy-images.js">Easy Lazy Images</a> concept, reimagined as a modern custom element.</p>]]></content><amg:twitter><![CDATA[Want to skip loading images entirely on mobile? Here’s a web component that does just that.]]></amg:twitter><amg:summary><![CDATA[The lazy-img web component goes beyond native lazy loading and srcset—it can completely skip loading images on small screens, saving bandwidth where it matters most.]]></amg:summary><summary type="html"><![CDATA[<p>The lazy-img web component goes beyond native lazy loading and srcset—it can completely skip loading images on small screens, saving bandwidth where it matters most.</p>]]></summary><category term="web components" /><category term="progressive enhancement" /><category term="HTML" /><category term="performance" /><category term="images" /><category term="responsive design" /></entry><entry><id>https://www.aaron-gustafson.com/notebook/jail-ing-images-in-expressionengine/</id><title type="html"><![CDATA[✍🏻 JAIL-ing images in ExpressionEngine]]></title><link href="https://www.aaron-gustafson.com/notebook/jail-ing-images-in-expressionengine/" rel="alternate" type="text/html" /><published>2013-07-22T18:04:00Z</published><content type="html" xml:base="https://www.aaron-gustafson.com"><![CDATA[<p>A while back I came across a link to <a href="https://github.com/sebarmeli/JAIL">Sebastiano Armeli-Battana’s jQuery Asynchronous Image Loader</a> (JAIL) and filed it away to revisit when I had some time. I finally made some time this weekend.</p><p>JAIL’s a cool little script that takes care of lazy loading images for you in order to speed up initial page rendering. To use it, you implement the following markup pattern:</p><code>html   &lt;img class=&quot;jail&quot; src=&quot;blank.gif&quot; data-src=&quot;foo.png&quot; alt=&quot;&quot;/&gt;   &lt;noscript&gt;    &lt;img src=&quot;foo.png&quot; alt=&quot;&quot;/&gt;   &lt;noscript&gt; </code><p>This is pretty ingenious actually. Without JS, the actual image is served up, but with JavaScript, the blank image is displayed until JAIL lazy loads the real image path stored in the <code>data-src</code> attribute. You initialize JAIL like this:</p><code>js   $(function(){    $('img.jail').jail();   }); </code><p>Simple, right? Well, yes and no.</p><p>On a site that isn’t updated frequently and where a skilled front-end coder is involved, this is cake. That, however, is seldom the reality. Heck, even on this blog, remembering to use that pattern while authoring content in the backend is not terribly likely. I needed a way to make it easier. So I <a href="https://github.com/easy-designs/easy_jail.ee_addon">automated JAIL as an ExpressionEngine plug-in</a>.</p><p>With this plug-in I can automatically enable (or remove) JAIL at the template level with a simple tag pair: <code>exp:easy_jail:prep</code></p><code>html   {exp:easy_jail:prep}     {body}   {/exp:easy_jail:prep} </code><p>The plugin will hunt for any image elements inside the tag pair and convert them to use the JAIL markup pattern. By default, it uses a base-64 encoded representation of a blank GIF (a.k.a. a <a href="https://en.wikipedia.org/wiki/Data_URI_scheme">Data URI</a>) to reduce the number of requests, but you can override that with the path to your own image (or a different Data URI) using the <code>blank_img</code> property. You can also customize the <code>class</code> used for the blank image using the <code>class_name</code> property.</p><code>html   {exp:easy_jail:prep blank_img=&quot;/i/blank.gif&quot; class_name=&quot;my_class&quot;}     {body}   {/exp:easy_jail:prep} </code><p>Then it’s just a matter of including the JAIL JavaScript code and executing it. You can, of course, include Sebastiano’s script and your JAIL config in your own JavaScript build, but the plug-in also includes a convenience function to drop it in for you. Simply add the <code>exp:easy_jail:js</code> tag before the close of the <code>body</code> element (after jQuery of course):</p><code>html   &lt;script src=&quot;//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js&quot;&gt;&lt;/script&gt;   &lt;script&gt;window.jQuery || document.write('&lt;script src=&quot;/j/jquery.js&quot;&gt;&lt;\/script&gt;')&lt;/script&gt;   {exp:easy_jail:js} </code><p>As with the <code>exp:easy_jail:prep</code> tag, you can customize the JavaScript output using the <code>class_name</code> property to tell JAIL what to lazy load. You can also customize the JAIL configuraiton using the <code>config</code> property. Just pass in a valid JSON object describing the configuration you want. JAIL is pretty darn configurable. There are a ton of options available, but the most intriguing to me currently is <code>offset</code>. We’re using it here on the blog to load images when you scroll to within 300px of the top of the image. Here’s how you’d do that using the plug-in:</p><code>html   &lt;script src=&quot;//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js&quot;&gt;&lt;/script&gt;   &lt;script&gt;window.jQuery || document.write('&lt;script src=&quot;/j/jquery.js&quot;&gt;&lt;\/script&gt;')&lt;/script&gt;   {exp:easy_jail:js config=&quot;{offset:300}&quot;} </code><p>And there you have it. Simple, lazy loaded images without having to train content editors to author the relatively complex markup pattern. If you want to have a play, feel free to <a href="https://github.com/easy-designs/easy_jail.ee_addon">grab the code from Github</a> or <a href="https://github.com/easy-designs/easy_jail.ee_addon/fork">you can fork it and help us to make it even more useful</a>.</p>]]></content><amg:summary><![CDATA[A while back I came across a link to Sebastiano Armeli-Battana’s jQuery Asynchronous Image Loader ( JAIL ) and filed it away to revisit when I had some time. I finally made some time this weekend.]]></amg:summary><summary type="html"><![CDATA[<p>A while back I came across a link to Sebastiano Armeli-Battana’s jQuery Asynchronous Image Loader ( JAIL ) and filed it away to revisit when I had some time. I finally made some time this weekend.</p>]]></summary><category term="performance" /><category term="images" /><category term="ExpressionEngine" /></entry><entry><id>https://www.aaron-gustafson.com/notebook/iir-redux/</id><title type="html"><![CDATA[✍🏻 iIR Redux]]></title><link href="https://www.aaron-gustafson.com/notebook/iir-redux/" rel="alternate" type="text/html" /><published>2012-04-16T13:02:00Z</published><content type="html" xml:base="https://www.aaron-gustafson.com"><![CDATA[<p>A few years back, I wrote <a href="http://v2.easy-designs.net/articles/iIR/">a little article celebrating the fact that you could actually apply image-replacement techniques to images themselves</a>. At the time, I was using it mainly for converting black and white printer-friendly logos to colorized or reversed alpha-transparent PNGs, but I postulated that the technique could also easily be used to replace high resolution print-friendly imagery with web-ready graphics (impracticle as that may be). Little did I know, six years later we’d see the advent of ultra-high resolution handheld devices like the iPhone 4 and iPad 3. Hell, at the time I was still rocking a Treo.</p><p>In a few recent projects, we’ve been offering high resolution graphics—mainly logos, icons and the like only for now as we’re not looking to kill anyone’s mobile bandwidth allotment—to devices with a pixel density of two or more (<code class="css">@media screen and (min-pixel-density:2)</code>). Interestingly, the same technique I came up with years ago is perfectly suited for this purpose in addition to letting you set a small, low resolution baseline image (mobile-first, ya know), replacing it with larger and/or higher resolution images as real estate or device supports it.</p><p>For those not keen to read my original article, here’s the jist (or gist—harharhar): take your favorite image-replacement technique and apply it to an <code class="html">img</code> element. As a means of demonstrating the concept, here’s two images:</p><code>html   &lt;p id=&quot;social-links&quot;&gt;    &lt;a href=&quot;…&quot;&gt;&lt;img src=&quot;fb-print.png&quot; alt=&quot;Like us on Facebook&quot;/&gt;&lt;/a&gt;    &lt;a href=&quot;…&quot;&gt;&lt;img src=&quot;twitter-print.png&quot; alt=&quot;Follow us on Twitter&quot;/&gt;&lt;/a&gt;   &lt;/p&gt; </code><p>With those in place, you simply apply your preferred image-replacement technique to the <code class="html">img</code> elements. I’m partial to Leahy/Langridge:</p><code>css   #social-links img {    background: center center no-repeat;    display: inline-block;    height: 0;    width: 25px;    padding-top: 25px;    overflow: hidden;   }   #social-links img[src*=fb] {    background-image: url(fb-screen.png);   }   #social-links img[src*=twitter] {    background-image: url(twitter-screen.png);   } </code><p>All that’s required to re-purpose this technique for high resolution images is to add in the <code class="css">background-size</code> property (set to the dimensions of the original low density image, of course):</p><code>css   @media only screen and (-moz-min-device-pixel-ratio: 2),    only screen and (-ms-min-device-pixel-ratio: 2),    only screen and (-o-min-device-pixel-ratio: 2),    only screen and (-webkit-min-device-pixel-ratio: 2),    only screen and (min-device-pixel-ratio: 2)   {    #social-links img {    background: top left no-repeat;    background-size: 25px 25px;    display: inline-block;    height: 0;    width: 25px;    padding-top: 25px;    overflow: hidden;     }    #social-links img[src*=fb] {    background-image: url(fb-2x.png);     }    #social-links img[src*=twitter] {    background-image: url(twitter-2x.png);     }   } </code><p>I think it’s a pretty useful technique overall. Of course it’s only really useful for presentational images; it doesn’t really make sense for content images. And, of course, there’s still <a href="http://blog.cloudfour.com/how-apple-com-will-serve-retina-images-to-new-ipads/">the question of whether it’s advisable to load a high-resolution image for someone who may be on a metered connection</a>. If you are concerned about that sort of thing, take heart that <a href="http://dvcs.w3.org/hg/dap/raw-file/tip/network-api/index.html">the W3C is working on the issue</a>. In the meantime, however, you may want to consider <a href="https://github.com/adamdbradley/foresight.js">Foresight.js</a>.</p>]]></content><amg:summary><![CDATA[A few years back, I wrote a little article celebrating the fact that you could actually apply image-replacement techniques to images themselves . At the time, I was using it mainly for converting black and white printer-friendly logos…]]></amg:summary><summary type="html"><![CDATA[<p>A few years back, I wrote a little article celebrating the fact that you could actually apply image-replacement techniques to images themselves . At the time, I was using it mainly for converting black and white printer-friendly logos…</p>]]></summary><category term="responsive web design" /><category term="performance" /><category term="images" /></entry><entry><id>https://www.aaron-gustafson.com/notebook/png-color-oddities-in-ie/</id><title type="html"><![CDATA[✍🏻 PNG color oddities in IE]]></title><link href="https://www.aaron-gustafson.com/notebook/png-color-oddities-in-ie/" rel="alternate" type="text/html" /><published>2006-02-18T12:21:21Z</published><content type="html" xml:base="https://www.aaron-gustafson.com"><![CDATA[<p>While working on a new site, I started playing around a little more with 8-bit <abbr title="Portable Network Graphics">PNG</abbr> files, comparing them to GIFs. In a few cases the <abbr title="Portable Network Graphics">PNG</abbr> was smaller (it didn’t used to be that way, but perhaps Photoshop CS2 does a better job of compressing <abbr title="Portable Network Graphics">PNG</abbr> files or something), so used it. All was good until I started testing the design in <abbr title="Internet Explorer">IE</abbr>, where the colors were all off. Here’s a breakdown of how the same graphic (placed as a CSS background image against a background color equal to its own background color) rendered between the two browsers: <img alt="PNG comparison between Firefox 1.5 and Internet Explorer 6/7B2" src="/i/posts/2006-02-18/png_compare.png" style="margin: 1em auto 0pt; display: block; width: 400px;"/></p><p>I am well-aware of the issues regarding <abbr title="Internet Explorer">IE</abbr>’s handling of alpha transparency in 24-bit PNGs, but had not heard of any color-related issues with 8-bit PNGs in <abbr title="Internet Explorer 6">IE6</abbr>. I did a test in <abbr title="Internet Explorer 7 Beta 2">IE7B2</abbr> to see if the error was there too and it was.</p><p>I did some searching on Google and couldn’t seem to find any documentation on this bug, but it’s certainly something I’d recommend they fix for the final release of <abbr title="Internet Explorer 7">IE7</abbr>. For now, however, the only solutions appear to be adding color-correction to your CSS for <abbr title="Internet Explorer">IE</abbr> (if you are dead-set on using an 8-bit <abbr title="Portable Network Graphics">PNG</abbr>) or using a GIF.</p>]]></content><amg:summary><![CDATA[While working on a new site, I started playing around a little more with 8-bit PNG files, comparing them to GIFs. In a few cases the PNG was smaller (it didn’t used to be that way, but perhaps Photoshop CS 2 does a better job of…]]></amg:summary><summary type="html"><![CDATA[<p>While working on a new site, I started playing around a little more with 8-bit PNG files, comparing them to GIFs. In a few cases the PNG was smaller (it didn’t used to be that way, but perhaps Photoshop CS 2 does a better job of…</p>]]></summary><category term="CSS" /><category term="images" /><category term="web standards" /></entry><entry><id>https://www.aaron-gustafson.com/notebook/browse-flickr-with-the-stroke-of-a-pen/</id><title type="html"><![CDATA[✍🏻 Browse Flickr with the stroke of a pen]]></title><link href="https://www.aaron-gustafson.com/notebook/browse-flickr-with-the-stroke-of-a-pen/" rel="alternate" type="text/html" /><published>2006-01-11T18:10:11Z</published><content type="html" xml:base="https://www.aaron-gustafson.com"><![CDATA[<p>This is perhaps the coolest (albeit experimental) way to browse <a href="http://www.flickr.com">Flickr</a>: <a href="http://labs.systemone.at/retrievr/">retrievr</a> from <a href="http://labs.systemone.at/">System One Labs</a>.</p>]]></content><amg:summary><![CDATA[This is perhaps the coolest (albeit experimental) way to browse Flickr : retrievr from System One Labs .]]></amg:summary><summary type="html"><![CDATA[<p>This is perhaps the coolest (albeit experimental) way to browse Flickr : retrievr from System One Labs .</p>]]></summary><category term="experiments" /><category term="images" /></entry></feed>