Goal: static images with animations shown on :hover that do not exceed container width.
Fixed code:
/* wrapper paragraph*/
.rimg {
text-align: center;
overflow: hidden;
}
/* rely on contents for vertical size, show backgrund centered */
.rimg-gif, .rimg-png {
display: block;
position: relative;
background-size: auto 100%;
background-position: center;
background-repeat: no-repeat;
line-height: 0;
}
/* containers need max-width in IE */
.rimg img, .rimg-gif, .rimg-png {
margin: 0;
max-width: 99.99999%; /* Opera Mini ignores anything above this % */
max-width: calc(100% - 0px); /* for proper browsers */
}
/* hide the GIF background unless hovered */
.rimg-gif:not(:hover) {
background-image: none !important;
}
/* hide the static image when hovered */
.rimg-gif:hover img {
opacity: 0;
}
<p class="rimg">
<span class="rimg-png" style="background-image:url(https://i.imgur.com/iwczbln.png)">
<a class="rimg-gif" target="_blank" href="https://i.imgur.com/TLxp2di.gif" style="background-image:url(https://i.imgur.com/TLxp2di.gif)">
<img src="https://i.imgur.com/iwczbln.png">
</a>
</span>
Description
</p>
Final structure:
.rimg
is just a container element for center-aligning things.img
is the static image (for semantics, printing, and default display). It is hidden via opacity when hovering, which allows to use the context menu to both get URL of GIF ("link") and static PNG ("image address")..rimg-gif
is the animated background GIF that is displayed when hovering (while hiding the static image). It is not loaded until hover. Doubles as a link to the actual GIF (for mobile users).rimg-png
has a static background and is there solely so that the reader doesn't see the image briefly flashing before the GIF finishes loading the first frame.There were a few issues with this:
In IE<=11 (non-Edge) sizing to fit width just outright doesn't work - the elements overflow the container instead.
Adding "max-width: 100%" to nested blocks fixed this (by this explanation).
Opera Mini similarly doesn't resize the images to fit container width, but aforementioned fixes for IE have no effect.
I was not able to find any explanations of this, but turns out that Opera Mini simply ignores max-width values roughly equal to 100% (>99.99999%). So I added that for Opera, and max-width: calc(100% - 0px)
for modern browsers.
On StackOverflow's snippet preview, calculated height is slightly higher than that of image, which can be seen by it briefly starting to repeat on the bottom. The issue disappears by giving line-height: 0
to .rgif-alt
but I'm not sure if that's a hack or not.
Edit: apparently so? Other options include float'ing the elements and using position: absolute, so I guess line-height is pretty alright for elements
Additional details:
If anything is unclear, do tell.
After a bit of trial and error I managed to resolve the issues by myself, so I added notes on solutions and the final (working) code to the question.
I'm not 100% happy with opening a new tab on Android (ideally should play when single-tapping), but all tested browsers close such popup-tabs when pressing Back so maybe it's not too bad. I added a "play" button, which also doubles as a first touch event absorber for mobile (initially covers the link completely, resized to 0% width after a short delay to allow clicking the link). This works both for modern browsers (which trigger :hover and animation playback on first tap and can open link on second tap) and for Opera Mini (which simply opens a popup tab with the GIF). You can see this in action here, for example.