Skip to content
:shipit: AVIF polyfill polyfill for the browser
Branch: master
Clone or download
Latest commit 1449c91 Mar 21, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
demo Fix demo CSS Mar 19, 2019
.gitignore Add gh-pages demo Mar 3, 2019
COPYING Initial commit Mar 3, 2019
avif-sw.js Fix BMP stride calc Mar 20, 2019
avif.js Fix video decoding in Chrome Mar 20, 2019

AVIF (AV1 Still Image File Format) polyfill for the browser
Start using superior image compression today! :shipit:
🎊 🎉 DEMO 🎉 🎊


  • Small, no dependencies, <3kb minified & gzipped
  • Intercepts AVIF fetch requests so works in any scenario
  • Uses native browser decoder and should be reasonably fast

Supported browsers

  • Chrome Desktop 70+
  • Firefox 63+ (with media.av1.enabled activated)
  • Firefox for Android 64+ (with media.av1.enabled and media.av1.use-dav1d activated)
  • Edge 18+ (with AV1 Video Extension installed)
  • Bromite 71+

After AV1 polyfill is implemented, Safari and elder browsers should work too.


npm install avif.js
// Put this to reg.js and serve avif-sw.js from web root
  <!-- Register worker -->
  <script src="reg.js"></script>

  <!-- Can embed AVIF with IMG tag now -->
  <img src="image.avif">

  <!-- Or via CSS property -->
  <div style="background: url(image2.avif)">
    some content

That's it! Service worker will detect all fetch requests for AVIF files and decode them on the fly. It works with any complex scenarios of image embedding you might have, e.g. background-image in external CSS or XMLHttpRequest from a script.

See demo directory for the usage example.

To generate AVIF files you may use go-avif CLI utility.

Technical details for nerds

AVIF file is basically an AV1 keyframe packed inside ISOBMFF container, almost identical to the HEIF structure, except AV1 video format instead of HEVC is used. Latest versions of Chrome and Firefox support AV1 video decoding, but still can't display AVIF images, it usually takes some time before new format will be added. See e.g. Firefox issue.

Though abovementioned technical aspects of AVIF make it quite easy to implement as a tiny polyfill. All we need to do is repack AVIF as a single-frame AV1 video and decode it using native decoder. This is exactly what avif.js does. First it fetches the AVIF file into binary buffer, then parses the ISOBMFF structure, then searches and extracts the actual frame data (OBUs) and finally embeds it into MP4 video file. Now we can decode that video with standard <video> element and dump raw pixel data to temporary <canvas>.

Instead of forcing users to call some function every time they need to display AVIF file, fetch event interceptor powered by Service Worker API is used. It allows us to replace image data that browser doesn't know how to decode with some known one. avif.js uses BMP to avoid spending time on second compression of already decoded pixel data. It's very fast operation, we just need to write BMP header and copy color values in order. Finally we can deliver that created on the fly .bmp back to the browser and our image will appear on the page.

The actual process is a bit more complex, e.g. we can't create <video> element in a worker, so pass decoding request to the main thread and get result back. Also container fields of the video should correspond to properties of the still image, some offsets need to be fixed and so on. But you got the general idea.

Limitations of Service Worker API

  • Needs to be served from HTTPS
  • Doesn't work in Firefox/Edge Private Window
  • Requires page reload on first visit to display static assets


  • Benchmark
  • Check for AVIF support
  • Support for browsers without Service Workers
  • Use full-blown decoder for browsers without AV1 support


avif.js is licensed under CC0.
Demo images are taken from av1-avif repo.

You can’t perform that action at this time.