It’s common to use iFrames to serve up content and track users on websites. Quite often you don’t need or want the iFrame to be visible.
While working on a browser extension for Chrome, Firefox, Edge, and Safari I used display: none to hide an iFrame. When the user clicked a button, the property changed from display: none to display: block. Easy right?
This obvious solution works great in Chrome, Firefox, and Edge. But in Safari, the div would never appear when display was set back to block.
It turns out that Safari won’t add iFrames with a display: none property to the DOM on the initial page load. This means that if you ever decide to reveal your element later, it won’t be available on the DOM. Yikes!
The Problem with visibility: hidden
You might think we could use visibility: hidden and visibility: visible to solve this. But if you set a parent container to visibility: hidden, its children will also be set to hidden. When you toggle visibility back to visible, the children will still be invisible.
You’ll have to set each child back to visible. Clunky and annoying.
You could also set the children to visibility: inherit, which will allow the parent container to set the child’s visibility. This is better, but still requires you to specify visibility on each child element.
My preferred solution is to use opacity. Here’s why.
On the initial page load, your iFrame can be invisible to the user, but Safari will still add it to the DOM. Awesome!
But it gets better still. By definition, child elements inherit their parent’s opacity. It doesn’t make sense that a container would be transparent if everything it contained was opaque.
So toggling our parent from opacity: 0 to opacity: 1 will make all child elements visible and invisible as needed. But we don’t have to fuss with visibility: inherit.
The opacity approach gets us there and Safari still adds it to the DOM on initial load.