RepoPilotOpen in app →

aFarkas/lazysizes

High performance and SEO friendly lazy loader for images (responsive and normal), iframes and more, that detects any visibility changes triggered through user interaction, CSS or JavaScript without configuration.

Mixed

Stale — last commit 2y ago

weakest axis
Use as dependencyMixed

last commit was 2y ago; no CI workflows detected

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isMixed

last commit was 2y ago; no CI workflows detected

  • 15 active contributors
  • MIT licensed
  • Tests present
  • Stale — last commit 2y ago
  • Concentrated ownership — top contributor handles 76% of recent commits
  • No CI workflows detected
What would change the summary?
  • Use as dependency MixedHealthy if: 1 commit in the last 365 days
  • Deploy as-is MixedHealthy if: 1 commit in the last 180 days

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Earn the “Healthy” badge

Current signals for aFarkas/lazysizes are Mixed. The embed flow is reserved for repos showing Healthy signals — the rest stay informational on this page so we're not putting a public call-out on your README. Address the items in the What would change the summary? dropdown above, then return to grab the embed code.

Common quick wins: green CI on default branch, no Critical CVEs in dependencies, recent commits on the default branch, a permissive license, and a published README.md with a quickstart.

Onboarding doc

Onboarding: aFarkas/lazysizes

Generated by RepoPilot · 2026-05-06 · Source

Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/aFarkas/lazysizes shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

Verdict

WAIT — Stale — last commit 2y ago

  • 15 active contributors
  • MIT licensed
  • Tests present
  • ⚠ Stale — last commit 2y ago
  • ⚠ Concentrated ownership — top contributor handles 76% of recent commits
  • ⚠ No CI workflows detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live aFarkas/lazysizes repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/aFarkas/lazysizes.

What it runs against: a local clone of aFarkas/lazysizes — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in aFarkas/lazysizes | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch gh-pages exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 793 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>aFarkas/lazysizes</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of aFarkas/lazysizes. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/aFarkas/lazysizes.git
#   cd lazysizes
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of aFarkas/lazysizes and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "aFarkas/lazysizes(\\.git)?\\b" \\
  && ok "origin remote is aFarkas/lazysizes" \\
  || miss "origin remote is not aFarkas/lazysizes (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify gh-pages >/dev/null 2>&1 \\
  && ok "default branch gh-pages exists" \\
  || miss "default branch gh-pages no longer exists"

# 4. Critical files exist
test -f "lazysizes.js" \\
  && ok "lazysizes.js" \\
  || miss "missing critical file: lazysizes.js"
test -f "lazysizes.d.ts" \\
  && ok "lazysizes.d.ts" \\
  || miss "missing critical file: lazysizes.d.ts"
test -f "Gruntfile.js" \\
  && ok "Gruntfile.js" \\
  || miss "missing critical file: Gruntfile.js"
test -f "package.json" \\
  && ok "package.json" \\
  || miss "missing critical file: package.json"
test -f "plugins/README.md" \\
  && ok "plugins/README.md" \\
  || miss "missing critical file: plugins/README.md"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 793 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~763d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/aFarkas/lazysizes"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

lazysizes is a high-performance, zero-configuration lazy loader for images (including responsive pictures and srcsets), iframes, and scripts that automatically detects visibility changes via user interaction, CSS animations, or JavaScript without requiring explicit configuration. It prioritizes rendering by distinguishing between in-viewport and near-viewport elements, and can automatically calculate the sizes attribute for responsive images. Single-library structure: core logic in lazysizes.js (main entry), minified distribution (lazysizes.min.js), UMD variant (lazysizes-umd.js), and a plugin ecosystem under plugins/ with subdirectories for each feature (artdirect, aspectratio, attrchange, bgset, etc.). Assets (CSS, JS bootstrap code, images) stored in assets/, with test pages at root level (index.html, animate.html, no-src.html) and demo subdir optimumx/. Build pipeline runs through Gruntfile.js.

Who it's for

Frontend developers and performance engineers building image-heavy websites who need SEO-friendly lazy loading without boilerplate configuration. Specifically valuable for teams implementing responsive images with picture/srcset syntax and needing to coordinate media queries between CSS and HTML.

Maturity & risk

Highly mature and production-ready. At version 5.3.2 with MIT license, this is an established library (based on the comprehensive test suite in qunitjs, Grunt build pipeline, and TypeScript definitions in lazysizes.d.ts). The project has extensive documentation, multiple plugins, and npm/bower distribution. Last activity and maintenance status not explicitly visible in provided data, but the presence of TypeScript typings and modern build tooling suggests active care.

Low risk for a mature lazy-loading library, but watch for: single-author maintenance (Alexander Farkas) with no visible team structure in package.json, potential browser API compatibility issues as browser lazy-loading native features mature, and the plugin architecture (plugins/ directory) means some features are optional—you must explicitly import needed plugins like respimg or parent-fit. No TypeScript source visible (only output .d.ts), so type safety is generated rather than native.

Active areas of work

Cannot determine from provided data—no recent commit info, PR list, or GitHub issues snapshot provided. Check the GitHub Issues page and Releases tab for current activity. The CHANGELOG.md file at the root would show version history.

Get running

git clone git://github.com/aFarkas/lazysizes.git
cd lazysizes
npm install
npm run build

Then open index.html in a browser to see demos, or inspect the test suite by running Grunt (see Gruntfile.js).

Daily commands:

npm run build

This runs Grunt tasks defined in Gruntfile.js (compilation, minification, TypeScript definitions). For tests: grunt qunit (inferred from devDependencies including qunitjs). Open test HTML pages directly in browser: index.html (main demos), animate.html (animation examples), no-src.html (fallback behavior).

Map of the codebase

  • lazysizes.js — Main entry point and core lazy-loading engine; all lazy-load logic, visibility detection, and image handling originates here
  • lazysizes.d.ts — TypeScript type definitions; required for understanding the public API contract and plugin interface
  • Gruntfile.js — Build configuration controlling minification, testing, and plugin compilation; essential for development workflow
  • package.json — Project metadata, dependencies, and npm scripts; defines build pipeline and entry points
  • plugins/README.md — Plugin architecture documentation; explains how the plugin system works and how to extend lazysizes
  • plugins/respimg/ls.respimg.js — Responsive images plugin; demonstrates core plugin pattern and handles srcset/picture element polyfills

How to make changes

Create a New Plugin

  1. Create plugin directory under plugins/ with README.md and source .js file following naming convention ls.pluginname.js (plugins/[pluginname]/ls.[pluginname].js)
  2. Hook into lazySizes via lazySizes.push() or lazySizes on API events (lazyunveil, lazyloaded, lazyloadingstarted) (plugins/[pluginname]/ls.[pluginname].js)
  3. Add plugin to Gruntfile.js uglify and concat tasks so it gets minified and distributed (Gruntfile.js)
  4. Document plugin usage, options, and examples in plugins/[pluginname]/README.md (plugins/[pluginname]/README.md)

Add a New Responsive Images Feature

  1. Update lazysizes.js to detect and handle new HTML5 image attributes or CSS properties (lazysizes.js)
  2. If image-specific, consider extending plugins/respimg/ls.respimg.js or creating specialized plugin (plugins/respimg/ls.respimg.js)
  3. Add TypeScript definitions to lazysizes.d.ts for any new public API methods (lazysizes.d.ts)
  4. Update README.md with usage examples and add test case to Gruntfile.js qunit configuration (README.md)

Fix a Browser Compatibility Issue

  1. Identify the issue and determine if it's in core lazysizes.js or a separate browser-specific plugin (lazysizes.js)
  2. Create or update a plugin under plugins/fix-[browsername]-[issue]/ with detection and workaround logic (plugins/fix-[browsername]-[issue]/ls.fix-[browsername]-[issue].js)
  3. Document the browser version affected and the fix in plugins/fix-[browsername]-[issue]/README.md (plugins/fix-[browsername]-[issue]/README.md)
  4. Add plugin to build pipeline via Gruntfile.js and update version in package.json (Gruntfile.js)

Why these technologies

  • IntersectionObserver API — Native browser API for efficient viewport visibility detection without jank; polyfilled via core for older browsers
  • JavaScript event-driven plugin model (lazySizes.push) — Decouples core lazy-loading from optional features (blur-up, srcset, background images); users pay only for what they use
  • data- attributes (data-src, data-srcset, data-sizes)* — Keeps layout HTML semantic and valid; prevents premature image downloads; works even with JavaScript disabled (via noscript plugin)
  • Grunt build pipeline with UglifyJS & JSHint — Maintains code quality and produces minimal distribution bundle (~8KB gzipped); max filesize checks prevent bloat
  • TypeScript definitions (lazysizes.d.ts) — Provides IDE autocomplete and type safety for plugin developers integrating lazysizes into TypeScript projects

Trade-offs already made

  • Event-driven plugin architecture over monolithic library

    • Why: Reduces core payload and allows tree-shaking; plugins only load if explicitly included
    • Consequence: Requires plugin knowledge to unlock features; more files to manage but better for performance-critical sites
  • IntersectionObserver with fallback over manual scroll polling

    • Why: Eliminates layout thrashing and improves performance; non-blocking visibility detection
    • Consequence: Older browsers require polyfill; library still works but with minor performance cost
  • No configuration API—detection is automatic

    • Why: Simpler API surface and self-initializing; 'just include and it works' experience
    • Consequence: Less explicit control; plugins extend configurability where needed; opt-out via class names instead of config object
  • CSS media query sharing (custommedia plugin) over hardcoded breakpoints

    • Why: DRY principle; HTML/CSS breakpoints stay in sync without duplication
    • Consequence: Requires data-media attribute on img/picture; adds light JS parsing of CSS media queries

Non-goals (don't propose these)

  • Does not handle authentication or user tracking
  • Not a real-time image sync service; no server-side component
  • Not a CDN or image optimization service (use external tools like Cloudinary)
  • Not a CSS framework or UI component library
  • Does not manage service workers or offline caching (plugins can extend this)

Traps & gotchas

Plugin imports: when using in ES6 modules, you must import plugins separately (e.g., import 'lazysizes/plugins/parent-fit/ls.parent-fit') and never use .min.js files from npm—only use non-minified source. Responsive image polyfills: lazysizes alone does not guarantee cross-browser support for picture/srcset; you must pair it with picturefill or the respimg plugin for older browsers (both listed in devDependencies). Self-initializing behavior: the library auto-detects images with class 'lazyload' on page load, so dynamically added images need manual triggering via lazySizes API (check demos for examples). Build artifacts: the build process generates lazysizes.min.js, UMD variant, and TypeScript definitions—never edit minified files directly.

Architecture

Concepts to learn

  • Intersection Observer API — lazysizes uses visibility detection to determine when to load images; understanding this browser API is key to grasping how lazy-loading is triggered without scroll listeners.
  • Responsive Images (picture and srcset) — The library's primary use case and core feature; you must understand media queries, descriptor syntax (widths, pixel density), and the art direction pattern to use lazysizes effectively.
  • Resource Priority Hinting (in-viewport vs. near-viewport) — lazysizes differentiates between images already visible and those close to entering viewport; understanding this prioritization strategy explains perceived performance gains.
  • data-* Attributes — The core API uses data-src, data-srcset, and data-sizes attributes instead of src; understanding why custom attributes matter for progressive enhancement and SEO is essential.
  • Progressive Enhancement — lazysizes gracefully degrades when JavaScript is disabled (thanks to src fallback) and supports SEO; this pattern is core to its design philosophy.
  • UMD (Universal Module Definition) — The library distributes as lazysizes-umd.js to support browsers, CommonJS (Node.js), and AMD modules; understanding UMD is necessary when integrating into various environments.
  • Plugin Architecture / Pub-Sub Pattern — lazysizes exposes hooks and registers extensions via the lazySizes namespace; understanding how plugins hook into core (seen in plugins/artdirect/, plugins/bgset/) teaches extensible library design.

Related repos

  • scottjehl/picturefill — Essential companion polyfill for cross-browser picture/srcset support; lazysizes recommends it for older IE and early Edge versions.
  • verlok/vanilla-lazyload — Direct competitor—lightweight pure JavaScript lazy loader; shows alternative approach without plugin system and with modern Intersection Observer API focus.
  • yocontra/node-imagemin — Complementary tool for image optimization pipeline; many lazysizes users pair it with imagemin for generating the multiple srcset variants that lazysizes loads.
  • imacrayon/adaptive-images — Related responsive image server-side solution; some lazysizes plugins (like RIAS) work with server-side adaptive logic for on-demand variant generation.
  • aFarkas/respimage — Authored by the same maintainer (Alexander Farkas); listed in devDependencies as testing dependency—lightweight respimg polyfill for lazy-loaded responsive images.

PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for blur-up plugin (ls.blur-up.js)

The blur-up plugin is a popular feature that shows low-quality image placeholders while high-res images load, but there are no visible unit tests in the repo structure for this plugin's core functionality. The test suite (using QUnit based on devDependencies) doesn't have dedicated blur-up test files. This would ensure the placeholder fade transition works correctly across browsers and doesn't regress.

  • [ ] Create test/blur-up.html or integrate tests into existing test suite following QUnit pattern
  • [ ] Test blur-up initialization with various image configurations
  • [ ] Test CSS class transitions (lqip → loaded state) with timing validation
  • [ ] Test edge cases: missing placeholders, rapid visibility changes, multiple blur-up instances
  • [ ] Reference plugins/blur-up/ls.blur-up.js and verify plugin integration with core lazysizes

Add GitHub Actions workflow for automated TypeScript compilation and type checking

The repo has a TypeScript configuration (lazysizes.d.ts, typescript in devDependencies, tsc in build script) but no visible CI workflow file in .github/workflows/. Currently, type compilation only happens locally before publish. This would catch TypeScript errors and type definition mismatches on every PR, preventing bugs from reaching users.

  • [ ] Create .github/workflows/typescript.yml workflow file
  • [ ] Configure workflow to run 'npm run build' (which includes tsc) on PR and push events
  • [ ] Add separate step to validate lazysizes.d.ts type definitions haven't regressed
  • [ ] Configure to fail the check if tsc reports type errors or if .d.ts file size increases unexpectedly
  • [ ] Document the workflow in CONTRIBUTING.md (if it exists) or README.md TypeScript section

Add integration tests for custommedia plugin media query behavior

The custommedia plugin (plugins/custommedia/ls.custommedia.js) allows sharing CSS media queries with HTML for responsive image sizing, but there are no visible tests validating that custom media queries are correctly parsed and applied. This is a complex feature that needs to handle CSS parsing, media descriptor matching, and interaction with the core lazySizes sizing algorithm.

  • [ ] Create test/custommedia.html QUnit test file
  • [ ] Test parsing of custom media attributes (e.g., --my-bp from CSS into HTML)
  • [ ] Test media query matching against various viewport sizes and device scenarios
  • [ ] Test interaction with responsive image srcset selection when custom media is used
  • [ ] Test edge cases: malformed media queries, circular references, media queries with AND operators
  • [ ] Reference plugins/custommedia/ls.custommedia.js and validate against README.md documented behavior

Good first issues

  • Add unit tests for the plugins/attrchange/ module in the qunit test suite (currently no dedicated test file visible in provided structure; check test directory for test coverage gaps).
  • Create an example HTML demo page showing integration with Shadow DOM or Web Components (current demos at index.html and optimumx/ focus on standard DOM; add use case for modern encapsulated components).
  • Document the lazy-loading performance metrics and measurement approach in README.md or a new PERFORMANCE.md file (library claims 'jank-free' and 'high performance' but provides no profiling guidance for users).

Top contributors

  • @aFarkas — 76 commits
  • [@Max Kloker](https://github.com/Max Kloker) — 4 commits
  • [@Oleksandr Kharchenko](https://github.com/Oleksandr Kharchenko) — 3 commits
  • @bordeo — 3 commits
  • @dependabot[bot] — 2 commits

Recent commits

  • 1523a4f — [typescript]: Add workaround to include better typescript support. (aFarkas)
  • 27c7ceb — update package (aFarkas)
  • bb45812 — Merge pull request #848 from aFarkas/dependabot/npm_and_yarn/ini-1.3.8 (aFarkas)
  • 499f0f8 — 5.3.2 (aFarkas)
  • d00a906 — Merge pull request #882 from styfle/patch-1 (aFarkas)
  • d05b164 — Move TS to devDependencies (styfle)
  • 81cf774 — 5.3.1 (aFarkas)
  • 2b6d24b — Types: Add some types (fixes #862) (aFarkas)
  • 9253212 — Types: Add some types (fixes #862) (aFarkas)
  • 0e985e8 — change issue templates (aFarkas)

Security observations

The lazysizes library has moderate security concerns primarily related to outdated dependencies (TypeScript, jQuery, Grunt ecosystem) that may contain unpatched vulnerabilities. The core library is a DOM manipulation tool with inherent XSS risks if attributes are not properly sanitized -

  • High · Outdated TypeScript Dependency — package.json - devDependencies. TypeScript version ^4.1.5 is significantly outdated (released January 2021). Modern versions contain security fixes and vulnerability patches that are not included in this version. Fix: Update TypeScript to the latest stable version (^5.x or current latest). Run 'npm audit' to identify security issues and update to patched versions.
  • High · Outdated jQuery Dependency — package.json - devDependencies. jQuery ^3.5.1 (released April 2020) is outdated and may contain unpatched vulnerabilities. Although jQuery 3.5.1 had some security improvements, newer versions contain additional patches. Fix: Update jQuery to ^3.6.0 or later. Review jQuery security advisories and apply latest patches. Consider if jQuery is still necessary as a dev dependency.
  • Medium · Potential DOM-based XSS in Lazy Loading Implementation — lazysizes.js and plugins/*. A lazy loading library that manipulates DOM attributes (data-src, src, srcset) has inherent XSS risks if user-controlled data is not properly sanitized before being set on DOM elements. The file structure suggests attribute manipulation without visible sanitization checks. Fix: Conduct thorough code review of attribute setting operations. Ensure all data sources are validated and sanitized. Use textContent or createElement instead of innerHTML. Implement Content Security Policy (CSP) headers. Add security tests for XSS payloads in data attributes.
  • Medium · Outdated Grunt and Build Tools — package.json - devDependencies (grunt related). Grunt ~1.1.0 and grunt-contrib-* packages are outdated (from 2018-2020 era). These tools may have unpatched vulnerabilities affecting the build process and supply chain security. Fix: Update to latest versions: grunt ~1.3.0+, grunt-contrib-uglify ^5.0.0+, grunt-contrib-watch ~1.1.0+. Run 'npm audit' and fix identified vulnerabilities. Consider migrating to modern build tools like webpack or esbuild.
  • Medium · Missing Security Headers Configuration — Root directory and demo HTML files. No visible security configuration files (no security.txt, no CSP headers configuration, no HSTS headers). Demo HTML files (animate.html, no-src.html, index.html) likely lack security headers. Fix: Add Content-Security-Policy headers to prevent XSS attacks. Implement X-Frame-Options, X-Content-Type-Options headers. Add HSTS header for HTTPS. Create a security.txt file. Configure headers in web server or add to HTML meta tags where appropriate.
  • Low · Incomplete Dependency Version Pinning — package.json - devDependencies. Use of caret (^) and tilde (~) version specifiers allows automatic updates to potentially breaking or untested versions. This affects supply chain security and reproducibility. Fix: Consider using npm ci and a lock file (package-lock.json exists but should be strictly reviewed). For production, consider pinning to exact versions. Regularly audit and update dependencies in controlled manner.
  • Low · Missing Security Documentation — Repository root. No SECURITY.md file found in the repository. This makes it difficult for security researchers to report vulnerabilities responsibly. Fix: Create a SECURITY.md file with vulnerability disclosure policy, contact information, and responsible disclosure guidelines. Reference GitHub security policy documentation.
  • Low · Potential Information Disclosure via BingSiteAuth.xml — BingSiteAuth.xml. BingSiteAuth.xml is a Bing verification file that may contain sensitive information or verification tokens if committed to version control. Fix: Verify this file doesn't contain sensitive credentials. Consider moving to .gitignore if it contains secrets. Add authentication tokens to .gitignore and use environment variables instead.

LLM-derived; treat as a starting point, not a security audit.

Where to read next


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · aFarkas/lazysizes — RepoPilot