element-closest
Lightweight polyfill for Element.closest and Element.matches
Repository Health
Technical Analysis
element-closest is a tiny polyfill that brings the DOM standard Element.closest() and Element.matches() methods to browsers that don’t support them natively, at roughly 257 bytes gzipped. closest() walks up the DOM tree from an element and returns the nearest ancestor (or the element itself) matching a CSS selector, which is a common building block for event delegation patterns.
The polyfill is applied by calling the exported function with a window reference, so it works equally in a <script> tag include or bundled via Browserify/Webpack in a Node-based build. It checks for existing vendor-prefixed matches implementations (msMatchesSelector, mozMatchesSelector, webkitMatchesSelector) before falling back to its own selector-matching implementation, and only defines closest if the browser doesn’t already provide it natively.
What You Get
- A drop-in polyfill for
Element.prototype.closest()per the DOM standard - A drop-in polyfill for
Element.prototype.matches(), including vendor-prefix detection - Both a browser
<script>build and a Node/bundler-friendly CommonJS/ESM build - A sub-1KB footprint (428 bytes raw, ~257 bytes gzipped)
- No-op behavior when native support already exists, so it’s always safe to include
Common Use Cases
- Supporting event delegation (
event.target.closest(selector)) in legacy browsers like IE8-11 - Adding safe
Element.matches()support without manually checking vendor prefixes - Shipping a minimal DOM polyfill bundle for older enterprise or embedded browser targets
Under The Hood
Architecture The entire implementation is a single exported polyfill(window) function in src/index.js: it first ensures Element.prototype.matches exists (falling back through vendor-prefixed variants, or implementing it manually by scanning querySelectorAll results), then defines Element.prototype.closest as a simple ancestor-walking loop that calls element.matches(selector) at each step until it finds a match or runs out of ancestors (nodeType !== 1). Tech Stack Authored in ES2015+ JavaScript and built with Rollup into three output formats: a UMD/global browser.js for <script> tag usage, a CommonJS index.js for Node/bundler usage, and an ESM index.mjs, with Babel used only for the browser build target. Code Quality The project’s only automated check is eslint src/*.js run via a pre-commit hook and as the test script — there is a test/test.js file present, but the primary quality gate is linting rather than an assertion-based test suite; this is a reasonable tradeoff given the tiny, single-function scope. API Design The polyfill is invoked explicitly with a window argument (elementClosest(window)) rather than auto-applying on import, which makes it SSR-safe and avoids surprising global side effects when bundled; consumers using the raw browser script get patching applied automatically on load instead.
Used by 2 apps in this directory
APITable
Low Code Platforms · Databases
API-first collaborative spreadsheet-database platform that auto-generates REST APIs and lets teams build internal tools, CRMs, and dashboards without code.
GDevelop
Developer Tools · Game Development · Design Tools
No-code, open-source game engine for building 2D, 3D and multiplayer games — publish to iOS, Android, Steam and the web.