diff --git a/css/components/headernav.css b/css/components/headernav.css
index f3dd3ec..0d07064 100644
--- a/css/components/headernav.css
+++ b/css/components/headernav.css
@@ -1,15 +1,18 @@
 /***** Header Nav Component *****/
 
-/* Read notes in component config */
-
 .c-headernav {
   --headernav-section-padding: var(--space3);
   --headernav-item-margin: var(--space3);
 
-  position: relative;
+  .no-popover & {
+    ul ul {
+      display: none;
+    }
+  }
 
   ul {
-    all: unset;
+    margin: unset;
+    padding: unset;
     list-style-type: none;
 
     li {
@@ -18,39 +21,35 @@
     }
   }
 
-  a {
-    display: block;
-  }
-
-  /* Sections: */
-  > ul {
-    @media (--min-width2) {
+  @media (--min-width2) {
+    a {
+      display: block;
+    }
+  
+    /* Sections: */
+    > ul {
       display: flex;
-
+  
       > li {
         flex: 1 1 auto;
       }
     }
-  }
-
-  > ul > li {
-    @media (--min-width2) {
+  
+    > ul > li {
       /* Nav bar main items: */
       &:not(:last-child) {
         border-inline-end: 1px solid oklch(55% 0 0deg);
       }
     }
-  }
-
-  /* Nav bar links: */
-  > ul > li > a {
-    @media (--min-width2) {
+  
+    /* Nav bar links: */
+    > ul > li > a {
       padding: var(--space1);
       background: linear-gradient(oklch(95% 0 0deg), oklch(88% 0 0deg));
       color: oklch(36% 0 0deg);
       text-align: center;
       text-decoration: none;
-
+  
       &:focus,
       &:hover {
         color: var(--color-blue);
@@ -60,9 +59,31 @@
   }
 
   /* Panels: */
-  > ul > li > ul {
-    display: none;
+
+  [popover] {
+    /* position-area: block-end span-inline-end; */
+    /* position-try-fallbacks: flip-inline; */
+    /* inset: unset; */
     position: absolute;
+    top: anchor(bottom);
+    left: anchor(left);
+    margin: 0;
+    transition-property: opacity, display, overlay;
+    transition-duration: .3s;
+    transition-behavior: allow-discrete;
+    border: unset;
+    opacity: 0;
+  
+    &:popover-open {
+      opacity: 1;
+  
+      @starting-style {
+        opacity: 0;
+      }
+    }
+  }
+
+  > ul > li > ul {
     padding: var(--headernav-section-padding);
     column-gap: calc(var(--headernav-section-padding) * 2);
     column-rule: 1px solid oklch(88% 0 0deg);
@@ -126,48 +147,4 @@
   > ul > li li {
     margin-block-end: var(--headernav-item-margin);
   }
-
-  /**** Panel Toggle ****/
-
-  /* If c-headernav JS not supported: */
-
-  &.c-headernav-no-js {
-    > ul > li:hover > ul {
-      @media (--min-width2) {
-        display: block;
-        z-index: 10;
-      }
-    }
-
-    /* If :focus-within not supported. Only primary links accessible via tabkey: */
-
-    > ul > li a:focus {
-      @media (--min-width2) {
-        display: block;
-        z-index: 10;
-      }
-    }
-
-    /* If :focus-within supported. All links accessbile via focus. No toggle state on primary links, so user must tab through every secondary link in each section to reach the next section: */
-
-    > ul > li:focus-within > ul {
-      @media (--min-width2) {
-        display: block;
-        z-index: 10;
-      }
-    }
-  }
-
-  /* If c-headernav JS supported: */
-
-  &.c-headernav-js {
-    /* Primary links disabled via JS and used as a toggle for each section. Hover and focus states handled by JS and set via 'open' class: */
-
-    li.open ul {
-      @media (--min-width2) {
-        display: block;
-        z-index: 10;
-      }
-    }
-  }
 }
diff --git a/css/components/mobilenav.css b/css/components/mobilenav.css
index 53e4ea4..ae6d945 100644
--- a/css/components/mobilenav.css
+++ b/css/components/mobilenav.css
@@ -42,6 +42,10 @@
           mask: url('data-url:npm:fa-light/angle-right.svg') center / 0.7rem no-repeat;
         }
       }
+
+      ul {
+        display: none;
+      }
     }
   }
 }
diff --git a/elements/3-components/headernav.hbs b/elements/3-components/headernav.hbs
index c8a8914..4f289e3 100644
--- a/elements/3-components/headernav.hbs
+++ b/elements/3-components/headernav.hbs
@@ -1,5 +1,4 @@
-{{!-- Read notes in component config --}}
-<nav aria-label="global" class="c-headernav c-headernav-no-js c-mobilenav">
+<nav aria-label="global" class="c-headernav c-mobilenav js-headernav">
   <ul>
     {{> @menu-items}}
   </ul>
diff --git a/elements/_template-default.hbs b/elements/_template-default.hbs
index 9d52d25..362b8f9 100644
--- a/elements/_template-default.hbs
+++ b/elements/_template-default.hbs
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<html lang="en">
+<html lang="en" class="no-popover">
 <head>
   <meta charset="utf-8">
   <title>CDLIB UI</title>
diff --git a/elements/_template-page.hbs b/elements/_template-page.hbs
index 58809d3..e872885 100644
--- a/elements/_template-page.hbs
+++ b/elements/_template-page.hbs
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<html lang="en">
+<html lang="en" class="no-popover">
 <head>
   <meta charset="utf-8">
   <title>CDLIB UI</title>
diff --git a/js/anchor-positioning.js b/js/anchor-positioning.js
new file mode 100644
index 0000000..2439ab8
--- /dev/null
+++ b/js/anchor-positioning.js
@@ -0,0 +1,19 @@
+// ***** Anchor Positioning Polyfill ***** //
+
+// Required for positioning elements that use the popover API.
+
+// https://github.com/oddbird/css-anchor-positioning
+
+const anchorPositioningPolyfill = async () => {
+  const { default: polyfill } = await import('@oddbird/css-anchor-positioning/dist/css-anchor-positioning-fn.js')
+
+  polyfill({
+    elements: undefined,
+    excludeInlineStyles: false,
+    useAnimationFrame: false
+  })
+}
+
+if (!('anchorName' in document.documentElement.style)) {
+  anchorPositioningPolyfill()
+}
diff --git a/js/headernav.js b/js/headernav.js
index f456dd8..2aa1928 100644
--- a/js/headernav.js
+++ b/js/headernav.js
@@ -1,62 +1,65 @@
-// Headernav Component:
+// Headernav Component //
 
+const headerNav = document.querySelector('.js-headernav')
+const subNavs = headerNav.querySelectorAll(':scope > ul > li:has(> ul)')
 const headerNavMediaQuery = window.matchMedia('(min-width: 760px)')
+let counter = 1
 
-function clickLink (event) {
-  if (this.parentElement.classList.contains('open') === false) {
-    this.parentElement.classList.add('open')
-    this.setAttribute('aria-expanded', 'true')
-  } else {
-    this.parentElement.classList.remove('open')
-    this.setAttribute('aria-expanded', 'false')
-  }
-  event.preventDefault()
-}
+if (document.querySelector('.c-headernav')) {
+  for (const subNav of subNavs) {
+    const subNavSiblingLink = subNav.querySelector('a')
+    const subNavPopover = subNav.querySelector('ul')
+    subNavPopover.popover = ''
+
+    // Anchor each sibling link to its popover using unique anchor names:
+    const anchorName = '--anchor' + counter++
+
+    // The properties 'anchor-name' and 'position-anchor' can't be set using style.setProperty in browsers that don't support them. Instead, use setAttribute to force them to appear in so that the anchor positioning polyfill sees them:
+    subNavSiblingLink.setAttribute('style', 'anchor-name: ' + anchorName)
+    subNavPopover.setAttribute('style', 'position-anchor: ' + anchorName)
+
+    const headerNavToggles = mq => {
+      const expandedState = () => {
+        if (subNavPopover.matches(':popover-open')) {
+          subNavSiblingLink.setAttribute('aria-expanded', 'true')
+        } else {
+          subNavSiblingLink.setAttribute('aria-expanded', 'false')
+        }
+      }
+
+      if (mq.matches) {
+        // Only a <button> as a popover control has built-in accessiblity bindings, so set and toggle sibling link aria expanded state:
+        subNavSiblingLink.setAttribute('aria-expanded', 'false') // initial state
 
-const headerNavToggles = e => {
-  if (document.querySelector('.c-headernav') && e.matches) {
-    const allMenuItems = document.querySelectorAll('.c-headernav > ul > li');
-
-    [].forEach.call(allMenuItems, function (el) {
-      document.querySelector('.c-headernav').classList.remove('c-headernav-no-js')
-      document.querySelector('.c-headernav').classList.add('c-headernav-js')
-      el.querySelector('a').setAttribute('aria-haspopup', 'true')
-      el.querySelector('a').setAttribute('aria-expanded', 'false')
-
-      el.addEventListener('mouseover', function (event) {
-        this.classList.add('open')
-        this.querySelector('a').setAttribute('aria-expanded', 'true')
-      })
-
-      el.addEventListener('mouseout', function (event) {
-        this.classList.remove('open')
-        this.querySelector('a').setAttribute('aria-expanded', 'false')
-      })
-
-      el.querySelector('a').addEventListener('click', clickLink)
-    });
-
-    [].forEach.call(allMenuItems, function (el) {
-      el.querySelector('a').addEventListener('focus', function (event) {
-        [].forEach.call(
-          allMenuItems,
-          function (el) {
-            if (el !== this.parentElement) {
-              el.classList.remove('open')
-              el.querySelector('a').setAttribute('aria-expanded', 'false')
-            }
-          }, this
-        )
-      })
-    })
-  } else {
-    const allMenuItems = document.querySelectorAll('.c-headernav > ul > li');
-
-    [].forEach.call(allMenuItems, function (el) {
-      el.querySelector('a').removeEventListener('click', clickLink)
-    })
+        // Show/hide subnav on mouse pointer over and out:
+        subNav.addEventListener('mouseover', () => {
+          subNavPopover.showPopover()
+          expandedState()
+        })
+
+        subNav.addEventListener('mouseout', () => {
+          subNavPopover.hidePopover()
+          expandedState()
+        })
+
+        // Toggle subnav if sibling link is clicked by keyboard return key:
+        subNavSiblingLink.addEventListener('click', (e) => {
+          subNavPopover.togglePopover()
+          e.preventDefault() // disable link from going to its URL when clicked
+          expandedState()
+        })
+
+        // Hide subnav when keyboard focus leaves its popover control:
+        subNav.addEventListener('focusout', (e) => {
+          if (!e.currentTarget.contains(e.relatedTarget)) {
+            subNavPopover.hidePopover()
+            expandedState()
+          }
+        })
+      }
+    }
+
+    headerNavMediaQuery.addEventListener('change', headerNavToggles)
+    headerNavToggles(headerNavMediaQuery)
   }
 }
-
-headerNavMediaQuery.addEventListener('change', headerNavToggles)
-headerNavToggles(headerNavMediaQuery)
diff --git a/js/main.js b/js/main.js
index 8da05c8..842d4e2 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1,6 +1,8 @@
+import './anchor-positioning.js'
 import './headernav.js'
 import './mediaqueries.js'
 import './newsreel.js'
+import './popover-support.js'
 import './sidebarposts.js'
 import './slideshow.js'
 import './toggles.js'
diff --git a/js/popover-support.js b/js/popover-support.js
new file mode 100644
index 0000000..2360e50
--- /dev/null
+++ b/js/popover-support.js
@@ -0,0 +1,5 @@
+// ***** Popover Support for CSS ***** //
+
+if (window.HTMLElement.prototype.hasOwnProperty('popover')) { // eslint-disable-line no-prototype-builtins
+  document.querySelector('html').classList.remove('no-popover')
+}
diff --git a/package-lock.json b/package-lock.json
index ddf8953..d00672b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,9 @@
       "name": "cdlib-ui",
       "version": "2.0.0",
       "license": "MIT",
+      "dependencies": {
+        "@oddbird/css-anchor-positioning": "^0.3.1"
+      },
       "devDependencies": {
         "@faker-js/faker": "^8.4.1",
         "@fortawesome/fontawesome-pro": "^6.6.0",
@@ -35,6 +38,10 @@
         "stylelint": "^16.8.1",
         "stylelint-config-property-sort-order-smacss": "^10.0.0",
         "stylelint-config-standard": "^36.0.1"
+      },
+      "engines": {
+        "node": "~20",
+        "npm": "~10"
       }
     },
     "node_modules/@allmarkedup/fang": {
@@ -319,6 +326,28 @@
         "npm": ">=6.14.13"
       }
     },
+    "node_modules/@floating-ui/core": {
+      "version": "1.6.8",
+      "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz",
+      "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==",
+      "dependencies": {
+        "@floating-ui/utils": "^0.2.8"
+      }
+    },
+    "node_modules/@floating-ui/dom": {
+      "version": "1.6.12",
+      "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz",
+      "integrity": "sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==",
+      "dependencies": {
+        "@floating-ui/core": "^1.6.0",
+        "@floating-ui/utils": "^0.2.8"
+      }
+    },
+    "node_modules/@floating-ui/utils": {
+      "version": "0.2.8",
+      "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz",
+      "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig=="
+    },
     "node_modules/@fortawesome/fontawesome-pro": {
       "version": "6.6.0",
       "resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-pro/-/6.6.0/fontawesome-pro-6.6.0.tgz",
@@ -982,6 +1011,51 @@
         "node": ">= 8"
       }
     },
+    "node_modules/@oddbird/css-anchor-positioning": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/@oddbird/css-anchor-positioning/-/css-anchor-positioning-0.3.1.tgz",
+      "integrity": "sha512-qjnCAoUkL7TpB5/QIUD+vqFWRUMa+HvDMT/PU9903jXZA3H9qc8Egtfj2JUh4KJN7RKSJ4ox5uLCarF57ACzGw==",
+      "dependencies": {
+        "@floating-ui/dom": "^1.6.11",
+        "@types/css-tree": "^2.3.8",
+        "css-tree": "^3.0.0",
+        "nanoid": "^5.0.7"
+      }
+    },
+    "node_modules/@oddbird/css-anchor-positioning/node_modules/css-tree": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.0.1.tgz",
+      "integrity": "sha512-8Fxxv+tGhORlshCdCwnNJytvlvq46sOLSYEx2ZIGurahWvMucSRnyjPA3AmrMq4VPRYbHVpWj5VkiVasrM2H4Q==",
+      "dependencies": {
+        "mdn-data": "2.12.1",
+        "source-map-js": "^1.0.1"
+      },
+      "engines": {
+        "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
+      }
+    },
+    "node_modules/@oddbird/css-anchor-positioning/node_modules/mdn-data": {
+      "version": "2.12.1",
+      "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.1.tgz",
+      "integrity": "sha512-rsfnCbOHjqrhWxwt5/wtSLzpoKTzW7OXdT5lLOIH1OTYhWu9rRJveGq0sKvDZODABH7RX+uoR+DYcpFnq4Tf6Q=="
+    },
+    "node_modules/@oddbird/css-anchor-positioning/node_modules/nanoid": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.8.tgz",
+      "integrity": "sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "bin": {
+        "nanoid": "bin/nanoid.js"
+      },
+      "engines": {
+        "node": "^18 || >=20"
+      }
+    },
     "node_modules/@one-ini/wasm": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
@@ -3112,6 +3186,11 @@
         "@types/node": "*"
       }
     },
+    "node_modules/@types/css-tree": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/@types/css-tree/-/css-tree-2.3.8.tgz",
+      "integrity": "sha512-zABG3nI2UENsx7AQv63tI5/ptoAG/7kQR1H0OvG+WTWYHOR5pfAT3cGgC8SdyCrgX/TTxJBZNmx82IjCXs1juQ=="
+    },
     "node_modules/@types/json5": {
       "version": "0.0.29",
       "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -15057,7 +15136,6 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
       "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
-      "dev": true,
       "engines": {
         "node": ">=0.10.0"
       }
diff --git a/package.json b/package.json
index bdc876e..b48eb54 100644
--- a/package.json
+++ b/package.json
@@ -115,5 +115,8 @@
         }
       ]
     }
+  },
+  "dependencies": {
+    "@oddbird/css-anchor-positioning": "^0.3.1"
   }
 }