Skip to content

sindresorhus/ponyfill

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Ponyfill

Like polyfill but with pony pureness




Use ponyfill.com for linking here.

What’s a ponyfill?

A ponyfill is an implementation of a standard, but without pretending to be it.

Unlike polyfills, ponyfills don't pretend to be the native API. They offer the same functionality through explicit imports and usage, keeping your code predictable and side-effect free.

The problem with polyfills

In JavaScript, a polyfill adds missing features by monkey patching the environment, typically by modifying globals like Array.prototype, Object, or window. This approach creates several problems:

  • The polyfill is only partially spec-compliant (sometimes unavoidable)
  • The spec changes
  • Another library polyfills the same thing differently

In general, you should not modify APIs you don’t own. Ponyfills avoid this entirely by staying pure.

It’s not just for JavaScript

  • JavaScript ponyfill: Exports functionality via a normal module, doesn’t patch anything
  • HTML ponyfill: Uses custom elements or classes to emulate new features
  • CSS ponyfill: Uses custom properties to simulate proposed syntax

Polyfill vs Ponyfill

Feature Polyfill Ponyfill
Patches global environment? Yes No
Aims to match spec exactly? Yes Often
Meant to be removed later? Yes Not necessarily
Causes global side effects? Yes No

Ponyfills are clear. Explicit. Honest. You use them directly and deliberately.

Examples

JavaScript

Polyfill

Number.isNaN ??= function (value) {
	return value !== value;
};
import 'is-nan-polyfill';

Number.isNaN(5);

Ponyfill

export default function isNaN(value) {
	return value !== value;
};
import isNanPonyfill from 'is-nan-ponyfill';

isNanPonyfill(5);

HTML

<!-- Instead of a future <card> element -->
<card-ponyfill>
	<h2 slot="title">Hello</h2>
</card-ponyfill>

<script>
	customElements.define('card-ponyfill', class extends HTMLElement {
		connectedCallback() {
			this.innerHTML = `<div class="card">${this.innerHTML}</div>`;
		}
	});
</script>

CSS

/* Instead of future syntax like @container */
:root {
	--container-sm: 480px;
	--container-lg: 768px;
}

.responsive-text[data-container='small'] {
	font-size: 0.875rem;
}

.responsive-text[data-container='large'] {
	font-size: 1.125rem;
}
<div class="responsive-text" data-container="small">Responsive text</div>

Why not use the native API in a ponyfill when available?

Ponyfills should avoid relying on native APIs unless unavoidable because:

  • Native APIs may behave inconsistently
  • Bugs or spec changes undermine confidence
  • Reimplementing avoids dependency on the environment

Use native APIs only when:

  • No alternative exists
  • Reimplementation would hurt performance or bundle size

How to create your own ponyfill

  1. Read the spec or explainer
  2. Implement the feature locally, without patching anything global
  3. Avoid assuming native API correctness unless necessary
  4. Write tests
  5. Publish a module or package
  6. Add ponyfill to the keywords field
  7. Link to ponyfill.com in your readme

Where can I find ponyfills?

Search npm.

Resources

License

CC0

To the extent possible under law, Sindre Sorhus has waived all copyright and related or neighboring rights to this work.

Header based on work by Mary Winkler.

About

🦄 Like polyfill but with pony pureness

Topics

Resources

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published