惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Blog — PlanetScale
Blog — PlanetScale
S
Security @ Cisco Blogs
G
GRAHAM CLULEY
L
LINUX DO - 热门话题
AWS News Blog
AWS News Blog
P
Privacy International News Feed
Cyberwarzone
Cyberwarzone
P
Proofpoint News Feed
腾讯CDC
美团技术团队
宝玉的分享
宝玉的分享
博客园 - 聂微东
小众软件
小众软件
T
Threat Research - Cisco Blogs
L
Lohrmann on Cybersecurity
雷峰网
雷峰网
T
Threatpost
The Hacker News
The Hacker News
P
Palo Alto Networks Blog
L
LangChain Blog
Cisco Talos Blog
Cisco Talos Blog
G
Google Developers Blog
V
Vulnerabilities – Threatpost
NISL@THU
NISL@THU
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Engineering at Meta
Engineering at Meta
T
Troy Hunt's Blog
F
Full Disclosure
博客园_首页
The Last Watchdog
The Last Watchdog
S
Secure Thoughts
H
Heimdal Security Blog
Hacker News: Ask HN
Hacker News: Ask HN
C
Check Point Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
PCI Perspectives
PCI Perspectives
Microsoft Security Blog
Microsoft Security Blog
S
Security Affairs
量子位
Cloudbric
Cloudbric
H
Hacker News: Front Page
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
L
LINUX DO - 最新话题
IT之家
IT之家
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Spread Privacy
Spread Privacy
Forbes - Security
Forbes - Security
Security Archives - TechRepublic
Security Archives - TechRepublic

Aaron Gustafson: Latest Posts & Links

LLM biased against accessible code (Claude Code issue #56079) :: Aaron Gustafson Can Your AI Pass the Accessibility Test? :: Aaron Gustafson Can Your AI Pass the Accessibility Test? :: Aaron Gustafson Fixing Accessibility After the Fact Is Too Late :: Aaron Gustafson Easy Data-entry Verification with a Web Component :: Aaron Gustafson Artificial Intelligence Has One Chance To Get Accessibility Right :: Aaron Gustafson Building a general-purpose accessibility agent—and what we learned in the process :: Aaron Gustafson Fixing Accessibility After the Fact Is Too Late :: Aaron Gustafson AI companies will fail. We can salvage something from the wreckage :: Aaron Gustafson Accessible faux-nested interactive controls :: Aaron Gustafson AI-assisted coding transforms PDF to web app using NYS Design System :: Aaron Gustafson Modern CSS Feature Support For Shadow DOM :: Aaron Gustafson AI is locking people out. At Scale. :: Aaron Gustafson The Incredible Overcomplexity of the Shadcn Radio Button :: Aaron Gustafson Accessibility in the End of Deterministic Design (Again) :: Aaron Gustafson Making keyboard navigation effortless :: Aaron Gustafson The WebAIM Million: The 2026 report on the accessibility of the top 1,000,000 home pages :: Aaron Gustafson Under the hood of MDN’s new frontend :: Aaron Gustafson Endgame for the Open Web :: Aaron Gustafson slideVars :: Aaron Gustafson AI is accidently making documentation accessible :: Aaron Gustafson Design systems can’t automate away all of your accessibility considerations :: Aaron Gustafson The Power of ‘No’ in Internet Standards :: Aaron Gustafson Nice Select :: Aaron Gustafson Visual Validation Feedback for Form Fields :: Aaron Gustafson Never Lose Form Progress Again :: Aaron Gustafson Different contexts, different tools, same person :: Aaron Gustafson Accessibility Assistant for Figma v52 :: Aaron Gustafson Some blind fans to experience Super Bowl with tactile device that tracks ball :: Aaron Gustafson Why we teach our students progressive enhancement :: Aaron Gustafson Repeatable Form Fields Made Simple :: Aaron Gustafson A Production-Ready Web Component Starter Template :: Aaron Gustafson Fullscreen Video and Iframes Made Easy :: Aaron Gustafson Dynamic Datalist: Autocomplete from an API :: Aaron Gustafson A Web Component for Obfuscating Form Fields :: Aaron Gustafson Forrester Research: As technology has evolved, so has the need for accessibility :: Aaron Gustafson Creating a more accessible web with ARIA Notify :: Aaron Gustafson Optimizing Your Codebase for AI Coding Agents :: Aaron Gustafson A Web Component for Conditionally Displaying Fields :: Aaron Gustafson Default Isn’t Design :: Aaron Gustafson Identifying Accessibility Data Gaps in CodeGen Models :: Aaron Gustafson Designing for Distress: Understanding Users in Crisis :: Aaron Gustafson Why I'm Betting Against AI Agents in 2025 (Despite Building Them) :: Aaron Gustafson Why AI Won’t Destroy Us with Microsoft’s Brad Smith :: Aaron Gustafson Learning Web Design, 6th Edition is out! :: Aaron Gustafson
Lazy Loading Images Based on Screen Size :: Aaron Gustafson
Aaron Gustafson · 2025-12-10 · via Aaron Gustafson: Latest Posts & Links

Native lazy loading and srcset are great, but they have a limitation: they always load some variant of the image. The lazy-img 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.

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?

The performance benefit

Unlike picture or srcset, which always load some image variant, lazy-img can completely skip loading images on screens or containers below your specified threshold. Set min-inline-size="768px" and mobile users will never download that image at all—saving data and speeding up page loads.

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 loaded and qualifies attributes (which we’ll get to shortly).

Basic usage

The lazy-img works pretty much identically to a regular img element, with all the attributes you know and love:

<lazy-img src="image.jpg" alt="A beautiful image"> </lazy-img>

But that’s not very interesting. The real power comes from conditional loading.

Container queries (default)

Load an image only when its container reaches a minimum width:

<lazy-img src="large-image.jpg" alt="Large image" min-inline-size="500px">
</lazy-img>

The image loads when the lazy-img element’s container reaches 500px wide. This is the default query mode—it uses ResizeObserver to watch the container size.

You can lazy load images based on viewport width instead by switching to media query mode:

<lazy-img
  src="desktop-image.jpg"
  alt="Desktop image"
  min-inline-size="768px"
  query="media"
>
</lazy-img>

With this configuration, the image loads when the browser window is at least 768px wide.

Load images when they scroll into view using IntersectionObserver by switching to the “view” query type:

<lazy-img src="image.jpg" alt="Loads when scrolled into view" query="view">
</lazy-img>

The default behavior (view-range-start="entry 0%") loads as soon as any part of the image enters the viewport.

Control when images load with the view-range-start attribute:

Load when 50% visible:

<lazy-img
  src="image.jpg"
  alt="Loads when half visible"
  query="view"
  view-range-start="entry 50%"
>
</lazy-img>

Preload before entering viewport:

<lazy-img
  src="image.jpg"
  alt="Preloads 200px before visible"
  query="view"
  view-range-start="entry -200px"
>
</lazy-img>

This creates a smooth user experience—images are already loaded by the time users scroll to them.

Responsive images

As with regular images, you can use srcset and sizes for responsive images:

<lazy-img
  src="image-800.jpg"
  srcset="image-400.jpg 400w,
          image-800.jpg 800w,
          image-1200.jpg 1200w"
  sizes="(max-width: 600px) 400px,
         (max-width: 1000px) 800px,
         1200px"
  alt="Responsive image"
  min-inline-size="400px"
>
</lazy-img>

The component waits until the conditions are met before loading a real image and the browser takes over from there.

Named breakpoints

You can also define named breakpoints using CSS custom properties:

:root {
  --lazy-img-mq: small;
}

@media (min-width: 768px) {
  :root {
    --lazy-img-mq: medium;
  }
}

@media (min-width: 1024px) {
  :root {
    --lazy-img-mq: large;
  }
}

Then reference them in your markup:

<lazy-img
  src="image.jpg"
  alt="Image with named breakpoints"
  named-breakpoints="medium, large"
  query="media"
>
</lazy-img>

The image loads when --lazy-img-mq matches “medium” or “large”.

Preventing layout shift

As with regular images, don’t forget to use width and height attributes to prevent Cumulative Layout Shift (CLS):

<lazy-img
  src="image.jpg"
  alt="A beautiful image"
  width="800"
  height="600"
  min-inline-size="768px"
>
</lazy-img>

The browser reserves the correct space while the image loads, preventing content from jumping around.

State attributes for styling

The component provides loaded and qualifies attributes you can use in CSS:

/* Hide images that loaded but no longer meet conditions */
lazy-img[loaded]:not([qualifies]) {
  display: none;
}

/* Show a placeholder for images that qualify but haven't loaded */
lazy-img[qualifies]:not([loaded])::before {
  content: "Loading…";
  display: block;
  padding: 2em;
  background: #f0f0f0;
  text-align: center;
}

Events

If you crave control, you can add your own functionality by listening for when images load:

const lazyImg = document.querySelector("lazy-img");
lazyImg.addEventListener("lazy-img:loaded", (event) => {
  console.log("Image loaded:", event.detail.src);
});

Performance

The component is highly optimized:

  • Throttled resize: Resize events are throttled to prevent excessive checks
  • Shared ResizeObserver: Multiple images observing the same container share a single ResizeObserver
  • Shared window resize listener: Media query mode shares a single window resize listener
  • Shared IntersectionObserver: View mode with the same view-range-start shares an IntersectionObserver
  • Clean disconnection: Properly cleans up observers when elements are removed

Even with hundreds of lazy-img elements on a page, performance remains excellent.

Progressive enhancement

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.

For critical images that are part of your content, use standard img tags. Use lazy-img for conditional enhancements.

Demo

Explore the demo to see container queries, media queries, scroll-based loading, and more in action:

Grab it

Check out the project on GitHub. Install via npm:

npm install @aarongustafson/lazy-img

Import and use:

import "@aarongustafson/lazy-img";

Based on my original Easy Lazy Images concept, reimagined as a modern custom element.