How to work around the Mobile Safari image resource limit
Because of the memory available on an iPad or iPhone, Mobile Safari has much stricter resource limits than most desktop browsers.
One of these limits is the total amount of image data that can be loaded on a single HTML page. When Mobile Safari has loaded between 8 to 10 MB of image data it will simply stop displaying any more images. It might even crash.
This limit doesn’t affect most websites since it’s generally a good idea to keep web pages reasonably small.
However, you can get in trouble with big image galleries and slideshows or with web applications that load new data asynchronously, for example to enable smooth ‘native’ transitions between different sections (yes, you can do those Flipboard transitions with Mobile Safari).
It would be entirely reasonable to expect to be able to work around this limitation by just removing image elements you no longer need:
Doesn’t work. For some reason, the actual image data does not get released when you remove an image element from the DOM (or an element containing one or more image elements). Bummer.
Wat does work is to set the src attribute of the image element to the url for a different (much smaller) image file:
When you replace the src attribute, the old image data gets released. Eventually.
I’ve tested this technique thoroughly and it turns out there are some things you have to be aware of:
-
The image data doesn’t get released immediately after you set the src attribute to a different image. It can take quite some time for the garbage collector to actually free the memory. This means you can still get into trouble if you add images too fast.
-
There’s no way to get Mobile Safari to load any additional images once it hit the image data resource, even if some or all of the loaded image data gets released. This even seems to persists across page reloads which means you may have to restart Mobile Safari while testing this technique (this nearly drove me insane).
-
If you also want to remove the image element from the DOM, you need to make sure the element cannot be garbage collected immediately after you’ve changed the src attribute. The old image data might not be released in this case. This is what works best for me:
As you can see I’m using a data URI for the replacement image. Credit for this tiniest GIF ever has to go to @pib.
When I explained this technique to Thomas Fuchs last week, he immediately added it to his excellent Zepto mobile WebKit framework. This weekend, I contributed a functional test you can use to try this for yourself.