Repository: oddbird/popover-polyfill
Pull request #236: Clean up styles for older browsers
Author: login: dvdherron
Created: 2025-02-26T15:12:16Z | Merged: 2025-03-24T19:22:41Z

![](https://source.unsplash.com/featured/?cute,animal&CHANGE_ME)
<!-- Swap `CHANGE_ME` for a random string to get a different image -->


<!--
## Description
Uncomment if you want to provide a custom description.
-->

## Related Issue(s)
Fixes #205 



## Steps to test/reproduce
-  On Sauce Labs, view the demo page in Safari 15 and 16 (Ventura OS) or versions of other browsers before they implemented cascade layers. 
- Compare the the deploy preview here to the live site. In the latest versions of browsers, everything should be the same (except for the updated `@layers` popover example). 

![image](https://github.com/user-attachments/assets/5664180f-9c80-40af-a7ec-a102a817e24a)


_Please explain how to best reproduce the issue and/or test the changes locally (including the pages/URLs/views/states to review)._



Linked issue #205: Demo Application Does Not Work in Safari 15 or 16
I wanted to evaluate the behavior of the polyfill in Safari 15 & 16 before integrating it into my project, so I opened the demo netlify app in each browser (I was using Saucelabs to access the browser), and in both cases, the styling of the demo app had issues:

In Safari 15, the demo application was usable, but completely unstyled.

In Safari 16, the demo application is completely unusable, as all the elements on the screen are invisible (except for the code samples, and, only when hovering, the OddBird logo in the nav bar).

It seems like, if the purpose of the library is to support older browsers, the demo app should probably work in older browsers. It certainly gives me pause as to the extent of the backwards compatible support if the demo app doesn't work in older browsers. 

How is the polyfill being tested in these browser environments? 

Note: I don't see any code for the demo app in this repo, but couldn't find a repo in your org that does have it. If there's a better place to file the ticket, please let me know.
Linked issue comments: user: login: jgerigmeyer
created_at: 2024-05-17T16:38:02Z
body: @spiralman Thanks for reporting! I'm able to reproduce what you're seeing in Safari 15, but Safari 16 looks mostly-fine to me, with the exception of some Shadow DOM content.

![20240517_16_31_46_safari_16](https://github.com/oddbird/popover-polyfill/assets/552316/fc5bd6aa-75ac-4fae-842e-6414cec3ccb7)

> It seems like, if the purpose of the library is to support older browsers, the demo app should probably work in older browsers. It certainly gives me pause as to the extent of the backwards compatible support if the demo app doesn't work in older browsers.

A fair point! We're working under very limited time/money resources at the moment, and just recently launched even the most basic version of a styled demo page -- whereas the polyfill itself has been used in production heavily over the past year. We'll take a look, but if you're willing to dig in and contribute that would be much appreciated!

> How is the polyfill being tested in these browser environments?

In CI at the moment we're testing against Chromium 113, Firefox 112, and Webkit 16.4.

> Note: I don't see any code for the demo app in this repo, but couldn't find a repo in your org that does have it. If there's a better place to file the ticket, please let me know.

Everything is here in the repo. The demo is served from [index.html](https://github.com/oddbird/popover-polyfill/blob/main/index.html), with styles in the [css folder](https://github.com/oddbird/popover-polyfill/tree/main/css).
author_association: MEMBER
user: login: jgerigmeyer
created_at: 2024-05-29T15:43:36Z
body: @stacyk or @dvdherron Could one of you look into this?
author_association: MEMBER
user: login: dvdherron
created_at: 2024-05-30T15:42:54Z
body: @jgerigmeyer I think there might be two things causing the styles not to show properly here. The oldest version of Safari probably doesn't have support for Cascade Layers. The issue in the later version of Safari is probably caused by lack of CSS support for nesting. I could rework some of the css so that we're not using nesting. As far as Layers support, I could unlayer some of the critical styles or we could use our polyfill?
author_association: CONTRIBUTOR
user: login: jgerigmeyer
created_at: 2024-05-30T15:44:53Z
body: > I could rework some of the css so that we're not using nesting. As far as Layers support, I could unlayer some of the critical styles or we could use our polyfill?

Those both sound reasonable to me, I'm fine with whatever you'd propose 👍 
author_association: MEMBER
user: login: dvdherron
created_at: 2024-06-17T10:08:26Z
body: @stacyk I only got so far as to test whether I was right about what was causing the style issues here. Nesting will obviously be an issue with some styles since that's one of the latest features to be implemented. But I think the main cause of style issues is layers. Like I mentioned above, we could either unlayer the bare minimum styles to have this work okay in older browsers, or make use of our polyfill. Container queries are used for styles here too, but I don't think them not working is having as drastic of an effect on the layout as layers/nesting. 
author_association: CONTRIBUTOR
user: login: jgerigmeyer
created_at: 2024-06-17T15:15:13Z
body: > Like I mentioned above, we could either unlayer the bare minimum styles to have this work okay in older browsers, or make use of our polyfill.

I think adding the layers polyfill is fine, if that's quickest and works well.
author_association: MEMBER
user: login: dvdherron
created_at: 2025-02-24T15:04:30Z
body: @mirisuzanne @jgerigmeyer The [demo site](https://popover-polyfill.netlify.app/) is importing individual stylesheets for each layer in a style tag in the head, similar to what we're doing on [workshops.oddbird.net](https://workshops.oddbird.net/). 

What would be the ideal way implement the layers polyfill with this setup? The polyfill is looking for a `.css` file and wouldn't find the `@import`s located in a `<style>` tag in the `<head>`, right? 

Would it be best to move all of those 'import's with their respective layers to, say, a `allstyles.css` style sheet? Or could the polyfill work with the current setup?
author_association: CONTRIBUTOR
user: login: jgerigmeyer
created_at: 2025-02-24T17:44:36Z
body: > What would be the ideal way implement the layers polyfill with this setup? The polyfill is looking for a `.css` file and wouldn't find the `@import`s located in a `<style>` tag in the `<head>`, right?

I think you're right -- we'd need to have all `@layer` references in an external stylesheet that gets preprocessed with postcss. Would it be easier to remove our use of layers (and nesting) for at least a basic version of this demo site?
author_association: MEMBER
user: login: mirisuzanne
created_at: 2025-02-24T20:17:21Z
body: @dvdherron The first thing I would try is just removing layers all together. I bet we would only have a couple issues that we could deal with using specificity tricks. For such a small site, that seems simpler than working in another polyfill. 
author_association: MEMBER

Diff:
diff --git a/README.md b/README.md
index 0ef1226..df4f081 100644
--- a/README.md
+++ b/README.md
@@ -132,15 +132,27 @@ some caveats which will need accommodations:
   observers or frameworks which do DOM diffing, or it may interfere with other
   code which sets `aria-expanded` on elements.
 
-- The polyfill uses `adoptedStyleSheets` to inject CSS onto the page (and each
-  Shadow DOM). If it can't use that it'll generate a `<style>` tag instead. This
-  means you may see a `<style>` tag you didn't put there, and this _may_ impact
-  mutation observers or frameworks.
-
-  - For browsers which don't support `adoptedStyleSheets` on Shadow Roots, if
-    you are building a ShadowRoot by setting `.innerHTML`, you'll remove the
-    StyleSheet. Either polyfill `adoptedStyleSheets` or call
-    `injectStyles(myShadow)` to add the styles back in.
+- The polyfill uses `adoptedStyleSheets` and `new CSSStyleSheet()` to inject CSS
+  onto the page (and each Shadow DOM). If it can't use that it'll generate a
+  `<style>` tag instead. This means you may see a `<style>` tag you didn't put
+  there, and this _may_ impact mutation observers or frameworks.
+
+  - For browsers which don't support `new CSSStyleSheet()`, if you are building
+    a ShadowRoot by setting `.innerHTML`, you'll remove the StyleSheet. Call
+    `injectStyles(myShadow)` to add the styles back in:
+
+    ```js
+    let supportsCSSStyleSheet = false;
+    try {
+      new CSSStyleSheet();
+      supportsCSSStyleSheet = true;
+    } catch {}
+    const myShadow = myHost.attachShadow({ mode: 'open' });
+    myShadow.innerHTML = `...`;
+    if (!supportsCSSStyleSheet) {
+      injectStyles(myShadow);
+    }
+    ```
 
   - Similarly, if you're using Declarative ShadowDOM or otherwise creating a
     shadow root without calling `attachShadow`/`attachInternals`, then the
diff --git a/css/base.css b/css/base.css
index a9873fd..26c3407 100644
--- a/css/base.css
+++ b/css/base.css
@@ -38,10 +38,11 @@ ul,
 ol {
   margin-inline: 2ch;
   padding-inline: unset;
+}
 
-  li & {
-    margin-block: 0;
-  }
+li ul,
+li ol {
+  margin-block: 0;
 }
 
 :focus-visible {
@@ -68,49 +69,47 @@ ol {
   padding: var(--half-shim) var(--double-gap);
   justify-content: var(--btn-content-align, center);
   justify-self: center;
+}
 
-  &:hover,
-  &:focus {
-    --button-state: var(--action);
-  }
+[data-btn]:hover,
+[data-btn]:focus {
+  --button-state: var(--action);
 }
 
 [popover] {
-  padding: 0.5em 1em;
-}
-
-a {
-  &:link,
-  &:visited {
-    --underline-color--default: var(--accent-color);
-    --underline-thickness--default: 0.1em;
-    --underline-offset--default: 0.15em;
-
-    color: var(--link, var(--action));
-    text-decoration: underline;
-    text-decoration-color: var(
-      --underline-color,
-      var(--underline-color--default)
-    );
-    text-decoration-thickness: var(
-      --underline-thickness,
-      var(--underline-thickness--default)
-    );
-    text-decoration-skip-ink: auto;
-    text-underline-offset: var(
-      --underline-offset,
-      var(--underline-offset--default)
-    );
-    transition: text-decoration-thickness 150ms ease-out;
-  }
-
-  &:hover,
-  &:focus {
-    --underline-color: var(--active);
-    --underline-thickness: 0.2em;
-
-    color: var(--link-focus, var(--active));
-  }
+  padding: var(--popover-padding, 0.5em 1em);
+}
+
+a:link,
+a:visited {
+  --underline-color--default: var(--accent-color);
+  --underline-thickness--default: 0.1em;
+  --underline-offset--default: 0.15em;
+
+  color: var(--link, var(--action));
+  text-decoration: underline;
+  text-decoration-color: var(
+    --underline-color,
+    var(--underline-color--default)
+  );
+  text-decoration-thickness: var(
+    --underline-thickness,
+    var(--underline-thickness--default)
+  );
+  text-decoration-skip-ink: auto;
+  text-underline-offset: var(
+    --underline-offset,
+    var(--underline-offset--default)
+  );
+  transition: text-decoration-thickness 150ms ease-out;
+}
+
+a:hover,
+a:focus {
+  --underline-color: var(--active);
+  --underline-thickness: 0.2em;
+
+  color: var(--link-focus, var(--active));
 }
 
 svg {
diff --git a/css/demo.css b/css/demo.css
index fa22ef9..214935c 100644
--- a/css/demo.css
+++ b/css/demo.css
@@ -1,4 +1,5 @@
 body {
+  --page-columns: minmax(auto, 1fr) minmax(0, 57ch) minmax(auto, 1fr);
   --page-margin: var(--double-gap);
   display: grid;
   grid-template: 'site-header' auto 'main' 1fr 'footer' auto / 100%;
@@ -15,27 +16,27 @@ body {
   margin-block-start: var(--page-margin);
 }
 
-#banner-logo {
-  &:link,
-  &:visited {
-    align-self: start;
-    display: block;
-    grid-area: logo;
-    transition: transform 300ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
-    transform-origin: top center;
-    z-index: 1;
-  }
+#banner-logo:hover,
+#banner-logo:focus,
+#banner-logo:active {
+  transform: scale(1.05);
+}
 
-  &:hover,
-  &:focus,
-  &:active {
-    transform: scale(1.05);
-  }
+#banner-logo [data-logo] {
+  height: auto;
+  block-size: auto;
+  width: 100%;
+  inline-size: 100%;
+}
 
-  [data-logo] {
-    block-size: auto;
-    inline-size: 100%;
-  }
+#banner-logo:link,
+#banner-logo:visited {
+  align-self: start;
+  display: block;
+  grid-area: logo;
+  transform-origin: top center;
+  transition: transform 300ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
+  z-index: 1;
 }
 
 [data-nav] {
@@ -51,8 +52,10 @@ body {
   list-style: none;
   margin-block: 0 var(--gap);
   padding: 0;
+}
 
-  @media (width >=40em) {
+@media (width >=40em) {
+  [data-navlist] {
     --nav-placement: start;
   }
 }
@@ -60,11 +63,11 @@ body {
 [data-nav] {
   display: inline-block;
   padding: 0 var(--gap);
+}
 
-  &:not(:hover, :active, :focus, [aria-current]) {
-    --underline-color: transparent;
-    --underline-thickness: 0;
-  }
+[data-nav]:not(:hover, :active, :focus, [aria-current]) {
+  --underline-color: transparent;
+  --underline-thickness: 0;
 }
 
 [data-layout='main'] {
@@ -73,18 +76,29 @@ body {
 
 .main-header {
   container: main-header / inline-size;
-  position: relative;
-  justify-content: center;
+  display: grid;
+  grid-template-columns: var(--page-columns);
   margin-inline: var(--page-margin);
+  position: relative;
+}
 
+.main-header > * {
+  grid-column: 2;
+}
+
+@supports (container: inline-size) {
   @media (width >=70em) {
-    align-items: var(--header-items-align, center);
-    display: flex;
-    gap: var(--double-gap);
+    .main-header {
+      align-items: var(--header-items-align, center);
+      display: flex;
+      gap: var(--double-gap);
+    }
   }
 
   @media (width >=1400px) {
-    --header-items-align: last baseline;
+    .main-header {
+      --header-items-align: last baseline;
+    }
   }
 }
 
@@ -93,26 +107,28 @@ body {
   grid-auto-rows: min-content;
   line-height: 0.8;
   margin-block: 0;
+}
 
-  @media (width >=56em) {
-    align-content: center;
+#title :not(.subtitle) {
+  color: var(--feature-to);
+  text-transform: uppercase;
+}
+
+@supports (background-clip: text) {
+  #title :not(.subtitle) {
+    background: var(--brand-pink);
+    background: var(--feature-gradient);
+    background-clip: text;
+    -webkit-box-decoration-break: clone;
+    box-decoration-break: clone;
+    color: transparent;
+    text-shadow: none;
   }
+}
 
-  & :not(.subtitle) {
-    color: var(--feature-to);
-    text-transform: uppercase;
-
-    @supports (background-clip: text) {
-      & {
-        background: var(--brand-pink);
-        background: var(--feature-gradient);
-        background-clip: text;
-        -webkit-box-decoration-break: clone;
-        box-decoration-break: clone;
-        color: transparent;
-        text-shadow: none;
-      }
-    }
+@media (width >=56em) {
+  #title {
+    align-content: center;
   }
 }
 
@@ -155,23 +171,24 @@ body {
   gap: var(--gap);
   grid-template-columns: minmax(auto, 1fr) minmax(0, 57ch) minmax(auto, 1fr);
   justify-items: center;
+  padding-inline: var(--page-margin);
   position: relative;
+}
 
-  &::before {
-    border-block-end: thin solid var(--border-color);
-    content: '';
-    inset: 0;
-    inset-block-end: auto;
-    position: absolute;
-  }
+.demo-section::before {
+  border-block-end: thin solid var(--border-color);
+  content: '';
+  inset: 0;
+  inset-block-end: auto;
+  position: absolute;
+}
 
-  &::after {
-    border-block-start: thin solid var(--border-color);
-    content: '';
-    position: absolute;
-    inset: 0 0 calc(var(--gap) * -2);
-    inset-block-start: auto;
-  }
+.demo-section::after {
+  border-block-start: thin solid var(--border-color);
+  content: '';
+  inset: 0 0 calc(var(--gap) * -2);
+  inset-block-start: auto;
+  position: absolute;
 }
 
 .demo-item {
@@ -187,24 +204,24 @@ body {
 [data-header] {
   grid-area: title;
   position: relative;
+}
 
-  [aria-hidden]:any-link {
-    display: inline-block;
-    filter: grayscale(var(--grayscale, 100%));
-    left: -1.25em;
-    position: absolute;
-    text-decoration: none;
-    transform: scale(var(--scale, 0.75));
-    transition: all 200ms ease-in-out;
-  }
+[data-header] [aria-hidden]:any-link {
+  display: inline-block;
+  filter: grayscale(var(--grayscale, 100%));
+  left: -1.25em;
+  position: absolute;
+  text-decoration: none;
+  transform: scale(var(--scale, 0.75));
+  transition: all 200ms ease-in-out;
+}
 
-  [aria-hidden]:hover,
-  [aria-hidden]:focus,
-  [aria-hidden]:active {
-    --grayscale: 0;
-    --scale: 1;
-    --outline-offset: 0.025em;
-  }
+[data-header] [aria-hidden]:hover,
+[data-header] [aria-hidden]:focus,
+[data-header] [aria-hidden]:active {
+  --grayscale: 0;
+  --outline-offset: 0.025em;
+  --scale: 1;
 }
 
 a[target='_blank']::after {
@@ -228,33 +245,17 @@ a[target='_blank']::after {
 
 [data-popover]:popover-open {
   align-items: center;
-  border: 1px solid var(--border-color);
+  border: var(--border-size) solid var(--border-color);
   box-shadow: 0 3px 3px var(--shadow);
   color: var(--popover-color, var(--text));
   display: flex;
-  font-family: var(--sans-serif);
   flex-wrap: wrap;
-  gap: var(--shim);
-
-  @media (width <=780px) {
-    inline-size: auto;
-    justify-content: center;
-    margin-inline: var(--shim);
-  }
-}
-
-/* for browsers that don't support popovers */
-[data-popover].\:popover-open {
-  align-items: center;
-  border: 1px solid var(--border-color);
-  box-shadow: 0 3px 3px var(--shadow);
-  color: var(--popover-color, var(--text));
-  display: flex;
   font-family: var(--sans-serif);
-  flex-wrap: wrap;
   gap: var(--shim);
+}
 
-  @media (width <=780px) {
+@media (width <=780px) {
+  [data-popover]:popover-open {
     inline-size: auto;
     justify-content: center;
     margin-inline: var(--shim);
@@ -262,20 +263,19 @@ a[target='_blank']::after {
 }
 
 [data-popover~='layered-styles'] {
-  --border-color: var(--text);
-  --popover-color: var(--bg);
+  --border-size: 2px;
 }
 
 [data-popover~='nested'] {
-  padding: 0;
+  --popover-padding: 0;
 }
 
 [data-popover~='manual'] {
   inset-block-end: var(--popover-offset);
+}
 
-  &:nth-of-type(2) {
-    inset-block-end: calc(var(--popover-offset) * 2);
-  }
+[data-popover~='manual']:nth-of-type(2) {
+  inset-block-end: calc(var(--popover-offset) * 2);
 }
 
 [data-popover~='inner-shadowed'] {
@@ -287,20 +287,20 @@ a[target='_blank']::after {
   --button-color: var(--text);
   --btn-content-align: start;
   --btn-inline-size: 100%;
+}
 
-  &:hover,
-  &:focus {
-    --button-color: var(--bg);
-    outline-color: transparent;
-  }
+[data-btn~='menu-item']:hover,
+[data-btn~='menu-item']:focus {
+  --button-color: var(--bg);
+  outline-color: transparent;
 }
 
 .site-footer {
   grid-area: footer;
   margin-block-start: var(--spacer);
   margin-inline: var(--page-margin);
-  position: relative;
   padding-block-end: var(--double-gap);
+  position: relative;
 }
 
 .menu-list {
@@ -315,3 +315,29 @@ a[target='_blank']::after {
     outline: none;
   }
 }
+
+/* for browsers that don't support popovers */
+@supports not selector(:popover-open) {
+  [popover]:not(.\:popover-open) {
+    display: none;
+  }
+
+  [data-popover].\:popover-open {
+    align-items: center;
+    border: 1px solid var(--border-color);
+    box-shadow: 0 3px 3px var(--shadow);
+    color: var(--popover-color, var(--text));
+    display: flex;
+    flex-wrap: wrap;
+    font-family: var(--sans-serif);
+    gap: var(--shim);
+  }
+
+  @media (width <=780px) {
+    [data-popover].\:popover-open {
+      inline-size: auto;
+      justify-content: center;
+      margin-inline: var(--shim);
+    }
+  }
+}
diff --git a/css/props.css b/css/props.css
index f897b41..08e8619 100644
--- a/css/props.css
+++ b/css/props.css
@@ -13,16 +13,18 @@ html {
   --code: var(--wf-code, var(--os-code, ui-monospace)), monospace, serif;
 
   /* scale */
-  --step-n1: clamp(0.9375rem, 0.8638rem + 0.3685cqi, 1.1494rem);
-  --step-0: clamp(1.125rem, 0.9511rem + 0.8696cqi, 1.625rem);
-  --step-1: clamp(1.35rem, 1.0204rem + 1.6478cqi, 2.2975rem);
-  --step-2: clamp(1.62rem, 1.0535rem + 2.8326cqi, 3.2488rem);
-  --step-3: clamp(1.9438rem, 1.0218rem + 4.6098cqi, 4.5944rem);
-  --step-6: clamp(3.3592rem, 2.8691rem + 2.4507cqi, 4.7684rem);
-  --step-7: clamp(4.0311rem, 3.36rem + 3.3555cqi, 5.9605rem);
-  --step-8: clamp(4.8373rem, 3.9283rem + 4.5448cqi, 17.4506rem);
-  --step-9: clamp(5.8048rem, 4.5844rem + 6.1017cqi, 19.3132rem);
-  --step-10: clamp(6.9657rem, 5.3393rem + 8.1319cqi, 19.6415rem);
+  --step-n1: clamp(0.9375rem, 0.814rem + 0.6173vw, 1.3542rem);
+  --step-0: clamp(1.125rem, 0.9769rem + 0.7407vw, 1.625rem);
+  --step-1: clamp(1.35rem, 1.1722rem + 0.8889vw, 1.95rem);
+  --step-2: clamp(1.62rem, 1.4067rem + 1.0667vw, 2.34rem);
+  --step-3: clamp(1.944rem, 1.688rem + 1.28vw, 2.808rem);
+  --step-4: clamp(2.3328rem, 2.0256rem + 1.536vw, 3.3696rem);
+  --step-5: clamp(2.7994rem, 2.4307rem + 1.8432vw, 4.0435rem);
+  --step-6: clamp(3.3592rem, 2.9169rem + 2.2118vw, 4.8522rem);
+  --step-7: clamp(4.0311rem, 3.5002rem + 2.6542vw, 5.8227rem);
+  --step-8: clamp(4.8373rem, 4.2003rem + 3.185vw, 6.9872rem);
+  --step-9: clamp(5.8048rem, 5.0403rem + 3.8221vw, 8.3846rem);
+  --step-10: clamp(6.9657rem, 6.0484rem + 4.5865vw, 10.0616rem);
 
   --small: var(--step-n1);
   --normal: var(--step-0);
@@ -30,13 +32,14 @@ html {
   --xlarge: var(--step-2);
   --h1: var(--xlarge);
   --title-size: var(--step-6);
+  --border-size: 1px;
 
-  --gap: clamp(12px, 2cqmin, 24px);
+  --gap: 0.75rem;
   --double-gap: calc(var(--gap) * 2);
   --shim: calc(var(--gap) / 2);
   --half-shim: calc(var(--shim) / 2);
   --quarter-shim: calc(var(--shim) / 4);
-  --spacer: clamp(1.5rlh, 10vw, 5rlh);
+  --spacer: calc(var(--double-gap) + 3vw);
 
   /* background colors */
   --bg: hsl(200 12% 95.098%);
@@ -66,3 +69,19 @@ html {
   --ccs-special--fg3: hsl(24deg 53% 27%);
   --ccs-accent--fg2: hsl(330deg 60% 35%);
 }
+
+@supports (font-size: 2cqi) {
+  html {
+    --step-n1: clamp(0.9375rem, 0.8638rem + 0.3685cqi, 1.1494rem);
+    --step-0: clamp(1.125rem, 0.9511rem + 0.8696cqi, 1.625rem);
+    --step-1: clamp(1.35rem, 1.0204rem + 1.6478cqi, 2.2975rem);
+    --step-2: clamp(1.62rem, 1.0535rem + 2.8326cqi, 3.2488rem);
+    --step-3: clamp(1.9438rem, 1.0218rem + 4.6098cqi, 4.5944rem);
+    --step-6: clamp(3.3592rem, 2.8691rem + 2.4507cqi, 4.7684rem);
+    --step-7: clamp(4.0311rem, 3.36rem + 3.3555cqi, 5.9605rem);
+    --step-8: clamp(4.8373rem, 3.9283rem + 4.5448cqi, 17.4506rem);
+    --step-9: clamp(5.8048rem, 4.5844rem + 6.1017cqi, 19.3132rem);
+    --step-10: clamp(6.9657rem, 5.3393rem + 8.1319cqi, 19.6415rem);
+    --gap: clamp(12px, 2cqmin, 24px);
+  }
+}
diff --git a/index.html b/index.html
index ec53c99..a3e9abb 100644
--- a/index.html
+++ b/index.html
@@ -12,22 +12,20 @@
       crossorigin
     />
     <style>
-      @layer reset, initial, popover-polyfill, default, demo;
-
-      @import url('/css/reset.css') layer(reset);
-      @import url('/css/demo.css') layer(demo);
-      @import url('/css/prism.css') layer(initial);
-      @import url('/css/fonts.css') layer(initial);
-      @import url('/css/base.css') layer(default);
-      @import url('/css/props.css') layer(initial);
-      @import url('/css/code.css') layer(default);
+      @import url('/css/reset.css');
+      @import url('/css/demo.css');
+      @import url('/css/prism.css');
+      @import url('/css/fonts.css');
+      @import url('/css/base.css');
+      @import url('/css/props.css');
+      @import url('/css/code.css');
     </style>
     <style>
       @layer popover-polyfill;
 
       @layer consumer {
         [data-popover~='layered-styles'] {
-          background-color: #d00d1e;
+          --border-color: #d00d1e;
         }
       }
     </style>
@@ -46,6 +44,17 @@
         note.innerText =
           'This browser does not support the Popover API natively, so the polyfill has been applied.';
       }
+
+      // If `new CSSStyleSheet()` isn't supported, then shadow roots that have
+      // content set using `.innerHTML(...)` will override the default injected
+      // stylesheets, and they'll need to be manually re-injected
+      window.supportsCSSStyleSheet = false;
+      try {
+        new CSSStyleSheet();
+        window.supportsCSSStyleSheet = true;
+      } catch {
+        // no support
+      }
     </script>
     <link rel="icon" type="image/x-icon" href="/favicon.ico" />
     <script src="https://unpkg.com/prismjs@v1.x/components/prism-core.min.js"></script>
@@ -181,7 +190,6 @@ <h1 id="title">
           Single Action Popover. This popover has an
           <a href="#" autofocus>autofocus link.</a>
         </div>
-        <div id="crossTreeHost"></div>
         <div id="menuPopover" data-popover="nested" popover>
           <ul class="menu-list">
             <li><button data-btn="menu-item">Item 1</button></li>
@@ -223,7 +231,7 @@ <h1 id="title">
           <div id="menuHost"></div>
         </div>
         <div id="layeredStylesPopover" data-popover="layered-styles" popover>
-          Popover with Layered Styles (should be red if browser has
+          Popover with Layered Styles (border should be red if browser has
           <code>@layer</code> support)
         </div>
 
@@ -422,23 +430,27 @@ <h2 data-header>
               >.</em
             >
           </p>
+          <div id="crossTreeHost"></div>
           <button id="crossTreeToggle" data-btn>
             Toggle Cross Tree Popover
           </button>
           <script type="module">
+            import { injectStyles } from './dist/popover-fn.js';
+
             const crossTreeHost = document.getElementById('crossTreeHost');
             const crossTreeShadowRoot = crossTreeHost.attachShadow({
               mode: 'open',
             });
             crossTreeShadowRoot.innerHTML = `
               <style>
-                @layer reset, initial, popover-polyfill, default, demo;
-
-                @import url('/css/demo.css') layer(demo);
-                @import url('/css/fonts.css') layer(initial);
-                @import url('/css/base.css') layer(default);
+                @import url('/css/demo.css');
+                @import url('/css/fonts.css');
+                @import url('/css/base.css');
               </style>
               <div id="crossTreePopover" popover data-popover>Shadowed Popover</div>`;
+            if (!window.supportsCSSStyleSheet) {
+              injectStyles(crossTreeShadowRoot);
+            }
             document.getElementById('crossTreeToggle').popoverTargetElement =
               crossTreeShadowRoot.getElementById('crossTreePopover');
           </script>
@@ -545,15 +557,15 @@ <h2 data-header>
             Toggle Menu with Shadowed Popover
           </button>
           <script type="module">
+            import { injectStyles } from './dist/popover-fn.js';
+
             const menuHost = document.getElementById('menuHost');
             const menuShadowRoot = menuHost.attachShadow({ mode: 'open' });
             menuShadowRoot.innerHTML = `
               <style>
-                @layer reset, initial, popover-polyfill, default, demo;
-
-                @import url('/css/demo.css') layer(demo);
-                @import url('/css/fonts.css') layer(initial);
-                @import url('/css/base.css') layer(default);
+                @import url('/css/demo.css');
+                @import url('/css/fonts.css');
+                @import url('/css/base.css');
               </style>
 
               <button popovertarget="shadowedMenuInner" data-btn>
@@ -562,6 +574,9 @@ <h2 data-header>
               <div id="shadowedMenuInner" data-popover="inner-shadowed" popover>
                 Inner Shadowed Popover
               </div>`;
+            if (!window.supportsCSSStyleSheet) {
+              injectStyles(menuShadowRoot);
+            }
           </script>
           <pre><code class="language-html"
 >&lt;!-- Light DOM --&gt;
@@ -616,7 +631,7 @@ <h2 data-header>
 
 &lt;div id="layeredStylesPopover" data-popover="layered-styles" popover&gt;
   Popover with Layered Styles
-  (should be red if browser has &lt;code&gt;@layer&lt;/code&gt; support)
+  (border should be red if browser has &lt;code&gt;@layer&lt;/code&gt; support)
 &lt;/div&gt;</code>
 
 <code class="language-css"
@@ -625,7 +640,7 @@ <h2 data-header>
 
 @layer consumer {
   [data-popover~='layered-styles'] {
-    background-color: #d00d1e;
+    --border-color: #d00d1e;
   }
 }</code></pre>
         </section>
@@ -640,17 +655,17 @@ <h2 data-header>
           </p>
           <div id="fullShadowHost"></div>
           <script type="module">
+            import { injectStyles } from './dist/popover-fn.js';
+
             const fullShadowHost = document.getElementById('fullShadowHost');
             const fullShadowRoot = fullShadowHost.attachShadow({
               mode: 'open',
             });
             fullShadowRoot.innerHTML = `
               <style>
-                @layer reset, initial, popover-polyfill, default, demo;
-
-                @import url('/css/demo.css') layer(demo);
-                @import url('/css/fonts.css') layer(initial);
-                @import url('/css/base.css') layer(default);
+                @import url('/css/demo.css');
+                @import url('/css/fonts.css');
+                @import url('/css/base.css');
               </style>
               <div id="shadowedPopover" popover data-popover>Shadowed Popover</div>
               <div>
@@ -664,6 +679,9 @@ <h2 data-header>
                   Toggle Shadowed Nested Popover
                 </button>
               </div>`;
+            if (!window.supportsCSSStyleSheet) {
+              injectStyles(fullShadowRoot);
+            }
           </script>
           <pre><code class="language-html"
 >&lt;!-- Shadow DOM --&gt;
@@ -692,6 +710,8 @@ <h2 data-header>
             <div><span>I’m a slotted element</span></div>
           </div>
           <script type="module">
+            import { injectStyles } from './dist/popover-fn.js';
+
             const shadowHostWithSlot =
               document.getElementById('shadowHostWithSlot');
             const shadowHostWithSlotRoot = shadowHostWithSlot.attachShadow({
@@ -699,11 +719,9 @@ <h2 data-header>
             });
             shadowHostWithSlotRoot.innerHTML = `
               <style>
-                @layer reset, initial, popover-polyfill, default, demo;
-
-                @import url('/css/demo.css') layer(demo);
-                @import url('/css/fonts.css') layer(initial);
-                @import url('/css/base.css') layer(default);
+                @import url('/css/demo.css');
+                @import url('/css/fonts.css');
+                @import url('/css/base.css');
               </style>
               <div id="shadowedPopoverWithSlot" popover data-popover><slot></slot></div>
               <div class="button-group">
@@ -711,6 +729,9 @@ <h2 data-header>
                   Toggle Shadowed Popover
                 </button>
               </div>`;
+            if (!window.supportsCSSStyleSheet) {
+              injectStyles(shadowHostWithSlotRoot);
+            }
           </script>
           <pre><code class="language-html"
 >&lt;!-- Light DOM --&gt;
diff --git a/tests/edge-cases.spec.ts b/tests/edge-cases.spec.ts
index d58e3ab..32e4564 100644
--- a/tests/edge-cases.spec.ts
+++ b/tests/edge-cases.spec.ts
@@ -25,5 +25,5 @@ test('styles in layers are winning over polyfilled styles', async ({
   page,
 }) => {
   const popover = (await page.locator('#layeredStylesPopover')).nth(0);
-  await expect(popover).toHaveCSS('background-color', 'rgb(208, 13, 30)');
+  await expect(popover).toHaveCSS('--border-color', '#d00d1e');
 });


Reviews:
user: login: jgerigmeyer
body: Looks good to me!

> The shadowed popovers in older browsers don't seem to be getting the "UA Stylesheet" styles we are injecting with JS. I think that's because we are using `.innerHTML` to create those elements @jgerigmeyer? These popovers aren't positioned so they push content around when they are opened.

Yeah, I think this is directly related to [this note](https://github.com/oddbird/popover-polyfill/blob/main/README.md?plain=1#L140-L143). I think I fixed it (conditionally re-injecting the styles in shadow roots) in https://github.com/oddbird/popover-polyfill/pull/236/commits/0f301bc618ad5c7c66b511281e489360851a5fa4 -- take a look and see what you think?
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-03T22:17:26Z
user: login: stacyk
body: @dvdherron Super close, just a small Safari 16 issue with I think lh units (the supports query only checks for cqi)
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-07T17:26:02Z
user: login: dvdherron
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T09:45:31Z
user: login: dvdherron
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T16:04:30Z
user: login: stacyk
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T17:20:57Z
user: login: dvdherron
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T09:07:54Z
user: login: stacyk
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-24T19:21:59Z

Review comments:
diff_hunk: @@ -315,3 +315,29 @@ a[target='_blank']::after {
     outline: none;
   }
 }
+
+/* for browsers that don't support popovers */
+@supports not selector(:popover-open) {
+  [popover]:not(.\:popover-open) {
+    display: none;
+  }
path: css/demo.css
user: login: stacyk
body: This one broke my brain for a while as that is the weirdest classname I've seen (there isn't anything to change here, just wanted to state how hard this was for me to read).
created_at: 2025-02-28T18:05:09Z
author_association: MEMBER
diff_hunk: @@ -315,3 +315,29 @@ a[target='_blank']::after {
     outline: none;
   }
 }
+
+/* for browsers that don't support popovers */
+@supports not selector(:popover-open) {
+  [popover]:not(.\:popover-open) {
+    display: none;
+  }
+
+  [data-popover].\:popover-open {
+    align-items: center;
+    border: 1px solid var(--border-color);
+    box-shadow: 0 3px 3px var(--shadow);
+    color: var(--popover-color, var(--text));
+    display: flex;
+    font-family: var(--sans-serif);
+    flex-wrap: wrap;
path: css/demo.css
user: login: stacyk
body: ```suggestion
    flex-wrap: wrap;
    font-family: var(--sans-serif);
```

:) 
created_at: 2025-02-28T18:10:52Z
author_association: MEMBER
diff_hunk: @@ -66,3 +69,20 @@ html {
   --ccs-special--fg3: hsl(24deg 53% 27%);
   --ccs-accent--fg2: hsl(330deg 60% 35%);
 }
+
+@supports (font-size: 2cqi) {
path: css/props.css
user: login: stacyk
body: So Safari 16 supports cqi, but it looks like it doesn't like the lh unit so spacer gets ignored. Still testing Safari 15 ... 

![Screenshot 2025-03-07 at 10 57 23 AM](https://github.com/user-attachments/assets/c3b6175b-31bb-42a8-a47f-3505a46e6b0c)
![Screenshot 2025-03-07 at 10 51 25 AM](https://github.com/user-attachments/assets/e8b174aa-d0bb-4ac3-b6dc-dd2793ab5861)

created_at: 2025-03-07T17:20:39Z
author_association: MEMBER
diff_hunk: @@ -66,3 +69,20 @@ html {
   --ccs-special--fg3: hsl(24deg 53% 27%);
   --ccs-accent--fg2: hsl(330deg 60% 35%);
 }
+
+@supports (font-size: 2cqi) {
path: css/props.css
user: login: dvdherron
body: good catch. fixed in https://github.com/oddbird/popover-polyfill/pull/236/commits/5ef1a52d3f3b1edf120ad7b6b27d287c711cdd78

Safari 16: 
https://github.com/oddbird/popover-polyfill/pull/236/commits/5ef1a52d3f3b1edf120ad7b6b27d287c711cdd78

![image](https://github.com/user-attachments/assets/de523492-2a2f-4a72-bbc5-acf8d3ad5891)

![image](https://github.com/user-attachments/assets/0c905330-9194-4626-91ed-083b0f9f8e5c)

And 15:
![image](https://github.com/user-attachments/assets/9919f3e4-2433-4d87-aba5-1d80042f4de5)

![image](https://github.com/user-attachments/assets/35ee6d06-7c4b-4505-893d-d4366a489a2b)




created_at: 2025-03-10T09:45:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -315,3 +315,29 @@ a[target='_blank']::after {
     outline: none;
   }
 }
+
+/* for browsers that don't support popovers */
+@supports not selector(:popover-open) {
+  [popover]:not(.\:popover-open) {
+    display: none;
+  }
+
+  [data-popover].\:popover-open {
+    align-items: center;
+    border: 1px solid var(--border-color);
+    box-shadow: 0 3px 3px var(--shadow);
+    color: var(--popover-color, var(--text));
+    display: flex;
+    font-family: var(--sans-serif);
+    flex-wrap: wrap;
path: css/demo.css
user: login: dvdherron
body: Sorry @stacyk , missed this somehow! Fixed in https://github.com/oddbird/popover-polyfill/pull/236/commits/b7626a8ae488e1451256320f9f4fe616ad4bac5d
created_at: 2025-03-17T16:04:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,27 +16,27 @@ body {
   margin-block-start: var(--page-margin);
 }
 
-#banner-logo {
-  &:link,
-  &:visited {
-    align-self: start;
-    display: block;
-    grid-area: logo;
-    transition: transform 300ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
-    transform-origin: top center;
-    z-index: 1;
-  }
+#banner-logo:hover,
+#banner-logo:focus,
+#banner-logo:active {
+  transform: scale(1.05);
+}
 
-  &:hover,
-  &:focus,
-  &:active {
-    transform: scale(1.05);
-  }
+#banner-logo [data-logo] {
+  block-size: auto;
+  height: auto;
+  inline-size: 100%;
+  width: 100%;
path: css/demo.css
user: login: stacyk
body: @dvdherron I didn't comment on these as I think we do actually want the more "modern" property last as it will be ignored if a browser doesn't understand it. So the order:

height
block-size
width
inline-size 

is probably what we want, but other than that,  I'd say this is good to merge!
created_at: 2025-03-17T17:19:35Z
author_association: MEMBER
diff_hunk: @@ -15,27 +16,27 @@ body {
   margin-block-start: var(--page-margin);
 }
 
-#banner-logo {
-  &:link,
-  &:visited {
-    align-self: start;
-    display: block;
-    grid-area: logo;
-    transition: transform 300ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
-    transform-origin: top center;
-    z-index: 1;
-  }
+#banner-logo:hover,
+#banner-logo:focus,
+#banner-logo:active {
+  transform: scale(1.05);
+}
 
-  &:hover,
-  &:focus,
-  &:active {
-    transform: scale(1.05);
-  }
+#banner-logo [data-logo] {
+  block-size: auto;
+  height: auto;
+  inline-size: 100%;
+  width: 100%;
path: css/demo.css
user: login: dvdherron
body: good catch. fixed in https://github.com/oddbird/popover-polyfill/pull/236/commits/5ebfc647404ed7cfb6db32bdf44d6ff5ce701c42 so I think this is good to merge!
created_at: 2025-03-18T09:07:53Z
author_association: CONTRIBUTOR

PR comments:
user: login: netlify[bot]
created_at: 2025-02-26T15:12:47Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *popover-polyfill* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 5ebfc647404ed7cfb6db32bdf44d6ff5ce701c42 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/popover-polyfill/deploys/67d937bf85f13800089ad42e |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-236--popover-polyfill.netlify.app](https://deploy-preview-236--popover-polyfill.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTIzNi0tcG9wb3Zlci1wb2x5ZmlsbC5uZXRsaWZ5LmFwcCJ9.aEI3o_DTMfx_8vRaQEsSNLX1dL5b_Xw6wQlvx1la-S0)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---
<!-- [popover-polyfill Preview](https://deploy-preview-236--popover-polyfill.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify site configuration](https://app.netlify.com/sites/popover-polyfill/configuration/notifications#deploy-webhooks)._
author_association: NONE
user: login: dvdherron
created_at: 2025-02-26T15:16:25Z
body: @stacyk I've removed the references here to layers (and most nesting). There's something happening that's causing a lot of the layout styles to not be applied. Testing on FF 95, custom properties are valid but not all of them are reflected in the styles of the page. Can you see the same thing in Safari 15?
author_association: CONTRIBUTOR
user: login: dvdherron
created_at: 2025-02-26T16:18:13Z
body: @stacyk I figured out why the size variables were not working. It's due to the `cq` units in the base sizes. 
author_association: CONTRIBUTOR
user: login: stacyk
created_at: 2025-02-26T17:51:34Z
body: @dvdherron I have Safari 18 and there isn't a way to downgrade that I know of, so using Saucelabs is the way to go for that. Sounds like you are on the right trail so let me know if you want a review when ready. 
author_association: MEMBER
user: login: dvdherron
created_at: 2025-02-27T21:14:09Z
body: @jgerigmeyer @stacyk I think this is ready for review. 

I removed the references to layers (except for the demo example). I changed the example from having a red background to having a red border. With the former, an old browser could not read the text (It was white text on a white background). 

I also removed nesting and added some `@support` for container query related styles. Its not perfect in older browsers, but I'm not sure how far back we want to fully support for this page. 

If you test this page on Safari 16, it seems to only work when you choose `Ventura` as an OS version. 

The shadowed popovers in older browsers don't seem to be getting the "UA Stylesheet" styles we are injecting with JS. I think that's because we are using `.innerHTML` to create those elements @jgerigmeyer? These popovers aren't positioned so they push content around when they are opened. 
author_association: CONTRIBUTOR
user: login: dvdherron
created_at: 2025-03-07T14:19:54Z
body: > Looks good to me!
> 
> > The shadowed popovers in older browsers don't seem to be getting the "UA Stylesheet" styles we are injecting with JS. I think that's because we are using `.innerHTML` to create those elements @jgerigmeyer? These popovers aren't positioned so they push content around when they are opened.
> 
> Yeah, I think this is directly related to [this note](https://github.com/oddbird/popover-polyfill/blob/main/README.md?plain=1#L140-L143). I think I fixed it (conditionally re-injecting the styles in shadow roots) in [0f301bc](https://github.com/oddbird/popover-polyfill/commit/0f301bc618ad5c7c66b511281e489360851a5fa4) -- take a look and see what you think?

Your changes fixed what I was seeing with the shadowed popovers. Thanks! This looks good to me. 
author_association: CONTRIBUTOR
user: login: dvdherron
created_at: 2025-03-24T16:01:45Z
body: @stacyk Ok, I think this still needs one more thumbs up from you and then this is ready to merge. 
author_association: CONTRIBUTOR