The dialog modal ::backdrop, CSS variables, and Safari



This content originally appeared on Go Make Things and was authored by Go Make Things

I love the native <dialog> element, and I love CSS variables. I make heavy use of both in Kelp.

Last week, I ran into yet another CSS bug around using CSS variables to style the ::backdrop on modal <dialog>’s in Safari on iOS.

The original Kelp CSS for the <dialog> element backdrop looked like this…

dialog {
	--backdrop-opacity: 0.5;
	/* The rest of the variables and styles... */
}

/**
 * Style the backdrop
 */
dialog:modal::backdrop {
	background-color: rgba(0, 0, 0, var(--backdrop-opacity));
}

This makes it really easy to set the ::backdrop opacity using a single CSS variable. You can change it globally like this…

dialog {
	--backdrop-opacity: 0.25;
}

Or just on specific <dialog> elements, like this…

<dialog style="--backdrop-opacity: 0.25">
	<!-- ... -->
</dialog>

This works in every browser… except Safari on iOS!

For some reason, Safari on iOS seems to not associate the ::backdrop with it’s <dialog>. As a result, the --backdrop-opacity variable cannot be found, the rgba() property gets an implicit value of 0, and the background becomes fully transparent.

This is exclusively an iOS issue. It works as expected in Safari on macOS.

The only way to fix it is to either…

  1. Hard-code your styles without a CSS variable.
  2. Apply the CSS variable to the :root, where in the ::backdrop on iOS Safari has access to it.
/**
 * This works
 */
dialog:modal::backdrop {
	background-color: rgba(0, 0, 0, 0.5);
}


/**
 * So does this
 */
:root {
	--backdrop-opacity: 0.5;
}

dialog:modal::backdrop {
	background-color: rgba(0, 0, 0, var(--backdrop-opacity));
}

Either way, you loose the ability to modify the variable in-context of the <dialog> element.

Like this? A Lean Web Club membership is the best way to support my work and help me create more free content.


This content originally appeared on Go Make Things and was authored by Go Make Things