I’ve been looking into ways to modify elements before DOMContentLoaded
so that enhancements can be made as an element is rendered to the screen allowing users to begin interacting with a page even if it hasn’t finished loading or if rendering is being blocked by 3rd party assets such as banner ads or tracking code. The most robust way to do this is to include an inline <script>
directly after each element you need to enhance which calls the relevant JavaScript functions — this works, but it’s not very DRY and it’s not easy to maintain.
Recently, I stumbled across a hack in an article by David Walsh which uses a CSS animation and the animationStart
event to detect when an element has been inserted into the DOM. It works by exploiting the fact that CSS animations run as soon as an element is appended to the document. Creating a simple animation that runs for a tiny duration and applying it to any elements you to want modify will fire a animationStart
event for each element as it’s inserted, essentially emulating the (now defunct) DOM mutation events. What’s great about this technique is it also works during page load!
The trick
Let’s say we want to enhance all <input>
fields:
We’ll need to set up a CSS animation and apply it to every <input>
field with CSS:
Finally, we need to make our “enhancements” with JavaScript:
That’s it. If the browser supports CSS animations all <input>
elements will be modified as the page loads.
Fallbacks
If the browser doesn’t support CSS animations we need a fallback to ensure these elements are still modified. Handling this case is actually really simple, just use DOMContentLoaded
or the window load
e!vent to fire the code you would have run in the animationStart
event. In this situation things will behave the way they always have.
Credit
Credit must go to David Walsh for his article and to Daniel Buchner for the original discovery. Also, James Allardice is working on wrapping this up into something easily deployable.