Implementing Freezeframe JS


One of the greatest challenges for a web designer is creating a site that is accessible to those with disabilities. It's one thing to create responsive sites and provide alt text for screen readers, but I noticed a lot of Neocities users' sites are lacking one of the most important aspects: avoiding seizure-inducing images.

As much as I do enjoy flashing images (blinkies, pixels, rainbow backgrounds, etc.), I've seen a lot of sites with so much blinking and flashing that I can't browse their site for very long without my eyes hurting. If my eyes hurt from browsing some sites, then I can't imagine what it must be like for those who are prone to seizures.

So, I started my journey to find out methods on allow others to enjoy these colorful GIFs but without the eyestrain, and that was when I found a magificent JS library called Freezeframe.js (demo page here).

With this library, animated GIFs are paused and can be enabled again by clicking/hovering the image or manually through a button and such.

It's an amazing library and it's saved me from a lot of eyestrain while debugging the graphics page. The instructions are pretty easy to follow, but I'd like share some more tips that I find might be helpful.

1) Installation

There are a few ways of installing freezeframe.js, but my preferred method is adding the following to your <head> tag on every page that you intend to use this library, preferably pages that are graphics-heavy.

<script src="https://unpkg.com/freezeframe/dist/freezeframe.min.js"></script>

If you'd like to make your own modifications to the script, there is always the option of downloading the entire thing from GitHub and saving it to one of your folders. It's up to you!

2) Setup in HTML

There are two ways of setting up freezeframe.js in HTML. You can set it up for each individual <img> tag, or you can set it up as a class for a <div> tag that holds several <img> elements inside, as shown below:

<img class="freezeframe" src="image.gif">

/* OR */

<div class="freezeframe">
  <img src="image1.gif">
  <img src="image2.gif">
  <img src="image3.gif">
</div>

For me, if I know all images in a div element will be animated (such as blinkies), then I place the freezeframe class into div element. Otherwise, if a div element has both static and animated images (like for links), then I place the freezeframe class into the img element.

This is only because I'm cautious about saving as much space as possible, since adding the freezeframe class to an element will automatically create a "loading" image, whether the original image is animated or not.

3) Implementing

One thing to note about the library is, like most scripts, it doesn't really work until the entire page has been loaded. You can put the script in your HTML file or in a separate JS file.

If you intend on using this library in your HTML file, then you can place the following code in one of two places: right above your </body> tag, or as an onload event in the </body> tag, as shown below.

<body>
  //...
  <script>new Freezeframe();</script>
</body>

/* OR */

<body onload="new Freezeframe();">
  //...
</body>

I personally would recommend putting the script in your HTML file if you intend on only using the script in just that file alone.

If you want to make sure it runs on all pages, then you can put it in your main JS file. However, you will need to make sure it will run after the entire page has been loaded. This can be done by using certain functions in Javascript or JQuery.

// Javascript
document.addEventListener("DOMContentLoaded", function(event) {
  new Freezeframe();
});

/* OR */

//JQuery
$(function() {
  new Freezeframe();
});

Once new Freezeframe(); is implemented, then all images with the freezeframe class will pause upon loading the page and will only play when the mouse hovers above them. Neat!

4) Customizing

Hovering over each frozen image is great and all, but when I first implemented the library, I wanted to create buttons that would play or pause ALL animated GIFs in a page. There unfortunately wasn't a lot of documention on how to achieve this, so here's how I did it!

The following steps are also why I prefer adding the Freezeframe library to my main script file, but hopefully they work on wherever you decide to implemented the library.

Make the buttons and give them appropriate labels so the script can locate them.

<button id="play-gif">Play GIFs</button>
<button id="stop-gif">Stop GIFs</button>

Then, go to the script you put new Freezeframe(); and change it into the following:

//Javascript
document.addEventListener("DOMContentLoaded", function(event) {
  const e = new Freezeframe();
  document.getElementById("#play-gif").addEventListener("click", function(){e.start()});
  document.getElementById("#stop-gif").addEventListener("click", function(){e.stop()});
});

/* OR */

// JQuery
$(function() {
  const e = new Freezeframe();
  $("#play-gif").on("click", function(){e.start()});
  $("#stop-gif").on("click", function(){e.stop()});
});

The functions that have "click" are what triggers the Freezeframe component to run a certain method, so clicking the button with the ID #play-gif will play the GIFs, while clicking the button with the ID #stop-gif will stop the GIFs.

So, you should have something like the following:

Doctor Strange stamp

Doctor Strange blinky

5) Limitations

Some limitations that I noticed include the following:

  1. Does not work with tabbed menus
  2. Incompatible with CSS styles that involve changing an image when hovering over it

If anyone else manages to find more limitations, let me know and I can add to this list. :)


Workaround for #1

(None yet)


Workaround for #2

/* Remove all transitions from Freezeframe elements */
a .ff-container.ff-active .ff-image,
a .ff-container.ff-inactive .ff-canvas.ff-canvas-ready {
  transition: none !important;
  -o-transition: none !important;
  -moz-transition: none !important;
  -webkit-transition: none !important;
}

/* Add the selectors for Freezeframe elements to wherever the image changes when hovered */
a:hover img,
a:hover .ff-container.ff-active .ff-image,
a:hover .ff-container.ff-inactive .ff-canvas.ff-canvas-ready {
  opacity: .5 !important;
}

/* This is only required if images become transparent when hovered*/
a:hover .ff-container.ff-inactive .ff-image {
  opacity: 0 !important;
}

6) Closing Thoughts

Hopefully this tutorial was helpful! I encourage everyone to implement this so your website can be enjoyed by almost anyone! :3

If you have any questions, feel free to throw an email my way. All I ask is that you try this on your own time instead of just copy and pasting the code I provided lol. I will not answer any emails that I find that could easily be solved from looking through the tutorial.